@@ -631,3 +631,114 @@ assert.throws(
631631 assert(stdout.includes('Verified OK'));
632632 }));
633633}
634+
635+ {
636+ // Test RSA-PSS.
637+ {
638+ // This key pair does not restrict the message digest algorithm or salt
639+ // length.
640+ const publicPem = fixtures.readKey('rsa_pss_public_2048.pem');
641+ const privatePem = fixtures.readKey('rsa_pss_private_2048.pem');
642+
643+ const publicKey = crypto.createPublicKey(publicPem);
644+ const privateKey = crypto.createPrivateKey(privatePem);
645+
646+ for (const key of [privatePem, privateKey]) {
647+ // Any algorithm should work.
648+ for (const algo of ['sha1', 'sha256']) {
649+ // Any salt length should work.
650+ for (const saltLength of [undefined, 8, 10, 12, 16, 18, 20]) {
651+ const signature = crypto.sign(algo, 'foo', { key, saltLength });
652+
653+ for (const pkey of [key, publicKey, publicPem]) {
654+ const okay = crypto.verify(
655+ algo,
656+ 'foo',
657+ { key: pkey, saltLength },
658+ signature
659+ );
660+
661+ assert.ok(okay);
662+ }
663+ }
664+ }
665+ }
666+ }
667+
668+ {
669+ // This key pair enforces sha256 as the message digest and the MGF1
670+ // message digest and a salt length of at least 16 bytes.
671+ const publicPem =
672+ fixtures.readKey('rsa_pss_public_2048_sha256_sha256_16.pem');
673+ const privatePem =
674+ fixtures.readKey('rsa_pss_private_2048_sha256_sha256_16.pem');
675+
676+ const publicKey = crypto.createPublicKey(publicPem);
677+ const privateKey = crypto.createPrivateKey(privatePem);
678+
679+ for (const key of [privatePem, privateKey]) {
680+ // Signing with anything other than sha256 should fail.
681+ assert.throws(() => {
682+ crypto.sign('sha1', 'foo', key);
683+ }, /digest not allowed/);
684+
685+ // Signing with salt lengths less than 16 bytes should fail.
686+ for (const saltLength of [8, 10, 12]) {
687+ assert.throws(() => {
688+ crypto.sign('sha256', 'foo', { key, saltLength });
689+ }, /pss saltlen too small/);
690+ }
691+
692+ // Signing with sha256 and appropriate salt lengths should work.
693+ for (const saltLength of [undefined, 16, 18, 20]) {
694+ const signature = crypto.sign('sha256', 'foo', { key, saltLength });
695+
696+ for (const pkey of [key, publicKey, publicPem]) {
697+ const okay = crypto.verify(
698+ 'sha256',
699+ 'foo',
700+ { key: pkey, saltLength },
701+ signature
702+ );
703+
704+ assert.ok(okay);
705+ }
706+ }
707+ }
708+ }
709+
710+ {
711+ // This key enforces sha512 as the message digest and sha256 as the MGF1
712+ // message digest.
713+ const publicPem =
714+ fixtures.readKey('rsa_pss_public_2048_sha512_sha256_20.pem');
715+ const privatePem =
716+ fixtures.readKey('rsa_pss_private_2048_sha512_sha256_20.pem');
717+
718+ const publicKey = crypto.createPublicKey(publicPem);
719+ const privateKey = crypto.createPrivateKey(privatePem);
720+
721+ // Node.js usually uses the same hash function for the message and for MGF1.
722+ // However, when a different MGF1 message digest algorithm has been
723+ // specified as part of the key, it should automatically switch to that.
724+ // This behavior is required by sections 3.1 and 3.3 of RFC4055.
725+ for (const key of [privatePem, privateKey]) {
726+ // sha256 matches the MGF1 hash function and should be used internally,
727+ // but it should not be permitted as the main message digest algorithm.
728+ for (const algo of ['sha1', 'sha256']) {
729+ assert.throws(() => {
730+ crypto.sign(algo, 'foo', key);
731+ }, /digest not allowed/);
732+ }
733+
734+ // sha512 should produce a valid signature.
735+ const signature = crypto.sign('sha512', 'foo', key);
736+
737+ for (const pkey of [key, publicKey, publicPem]) {
738+ const okay = crypto.verify('sha512', 'foo', pkey, signature);
739+
740+ assert.ok(okay);
741+ }
742+ }
743+ }
744+ }
0 commit comments