Note: the usual value for the salt length is the number of bytes in the hash function.
private void doTestSig( int id, RsaKeyParameters pub, RsaKeyParameters prv, byte[] slt, byte[] msg, byte[] sig) { PssSigner eng = new PssSigner(new RsaEngine(), new Sha1Digest(), 20); eng.Init(true, new ParametersWithRandom(prv, new FixedRandom(slt))); eng.BlockUpdate(msg, 0, msg.Length); byte[] s = eng.GenerateSignature(); if (!AreEqual(s, sig)) { Fail("test " + id + " failed generation"); } eng.Init(false, pub); eng.BlockUpdate(msg, 0, msg.Length); if (!eng.VerifySignature(s)) { Fail("test " + id + " failed verification"); } }
private bool isProcessingOkay( RsaKeyParameters pub, RsaKeyParameters prv, byte[] data, SecureRandom random) { RsaBlindingFactorGenerator blindFactorGen = new RsaBlindingFactorGenerator(); RsaBlindingEngine blindingEngine = new RsaBlindingEngine(); PssSigner blindSigner = new PssSigner(blindingEngine, new Sha1Digest(), 20); PssSigner pssEng = new PssSigner(new RsaEngine(), new Sha1Digest(), 20); random.NextBytes(data); blindFactorGen.Init(pub); BigInteger blindFactor = blindFactorGen.GenerateBlindingFactor(); RsaBlindingParameters parameters = new RsaBlindingParameters(pub, blindFactor); // generate a blind signature blindSigner.Init(true, new ParametersWithRandom(parameters, random)); blindSigner.BlockUpdate(data, 0, data.Length); byte[] blindedData = blindSigner.GenerateSignature(); RsaEngine signerEngine = new RsaEngine(); signerEngine.Init(true, prv); byte[] blindedSig = signerEngine.ProcessBlock(blindedData, 0, blindedData.Length); // unblind the signature blindingEngine.Init(false, parameters); byte[] s = blindingEngine.ProcessBlock(blindedSig, 0, blindedSig.Length); //verify signature with PssSigner pssEng.Init(false, pub); pssEng.BlockUpdate(data, 0, data.Length); return pssEng.VerifySignature(s); }
public override void PerformTest() { doTestSig(1, pub1, prv1, slt1a, msg1a, sig1a); doTestSig(2, pub1, prv1, slt1b, msg1b, sig1b); doTestSig(3, pub2, prv2, slt2a, msg2a, sig2a); doTestSig(4, pub2, prv2, slt2b, msg2b, sig2b); doTestSig(5, pub4, prv4, slt4a, msg4a, sig4a); doTestSig(6, pub4, prv4, slt4b, msg4b, sig4b); doTestSig(7, pub8, prv8, slt8a, msg8a, sig8a); doTestSig(8, pub8, prv8, slt8b, msg8b, sig8b); doTestSig(9, pub9, prv9, slt9a, msg9a, sig9a); doTestSig(10, pub9, prv9, slt9b, msg9b, sig9b); // // loop test - sha-1 only // PssSigner eng = new PssSigner(new RsaEngine(), new Sha1Digest(), 20); int failed = 0; byte[] data = new byte[DataLength]; SecureRandom random = new SecureRandom(); random.NextBytes(data); for (int j = 0; j < NumTests; j++) { eng.Init(true, new ParametersWithRandom(prv8, random)); eng.BlockUpdate(data, 0, data.Length); byte[] s = eng.GenerateSignature(); eng.Init(false, pub8); eng.BlockUpdate(data, 0, data.Length); if (!eng.VerifySignature(s)) { failed++; } } if (failed != 0) { Fail("loop test failed - failures: " + failed); } // // loop test - sha-256 and sha-1 // eng = new PssSigner(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), 20); failed = 0; data = new byte[DataLength]; random.NextBytes(data); for (int j = 0; j < NumTests; j++) { eng.Init(true, new ParametersWithRandom(prv8, random)); eng.BlockUpdate(data, 0, data.Length); byte[] s = eng.GenerateSignature(); eng.Init(false, pub8); eng.BlockUpdate(data, 0, data.Length); if (!eng.VerifySignature(s)) { failed++; } } if (failed != 0) { Fail("loop test failed - failures: " + failed); } }
private void testSig( int id, RsaKeyParameters pub, RsaKeyParameters prv, byte[] slt, byte[] msg, byte[] sig) { RsaBlindingFactorGenerator blindFactorGen = new RsaBlindingFactorGenerator(); RsaBlindingEngine blindingEngine = new RsaBlindingEngine(); PssSigner blindSigner = new PssSigner(blindingEngine, new Sha1Digest(), 20); PssSigner signer = new PssSigner(new RsaEngine(), new Sha1Digest(), 20); blindFactorGen.Init(pub); BigInteger blindFactor = blindFactorGen.GenerateBlindingFactor(); RsaBlindingParameters parameters = new RsaBlindingParameters(pub, blindFactor); // generate a blind signature blindSigner.Init(true, new ParametersWithRandom(parameters, new FixedRandom(slt))); blindSigner.BlockUpdate(msg, 0, msg.Length); byte[] blindedData = blindSigner.GenerateSignature(); RsaEngine signerEngine = new RsaEngine(); signerEngine.Init(true, prv); byte[] blindedSig = signerEngine.ProcessBlock(blindedData, 0, blindedData.Length); // unblind the signature blindingEngine.Init(false, parameters); byte[] s = blindingEngine.ProcessBlock(blindedSig, 0, blindedSig.Length); //signature verification if (!AreEqual(s, sig)) { Fail("test " + id + " failed generation"); } //verify signature with PssSigner signer.Init(false, pub); signer.BlockUpdate(msg, 0, msg.Length); if (!signer.VerifySignature(s)) { Fail("test " + id + " failed PssSigner verification"); } }
private void fixedSaltTest() { byte[] data = Hex.Decode("010203040506070809101112131415"); PssSigner eng = new PssSigner(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), Hex.Decode("deadbeef")); eng.Init(true, prv8); eng.BlockUpdate(data, 0, data.Length); byte[] s = eng.GenerateSignature(); eng.Init(false, pub8); eng.BlockUpdate(data, 0, data.Length); if (!eng.VerifySignature(s)) { Fail("fixed salt failed"); } // test failure eng = new PssSigner(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), Hex.Decode("beefbeef")); eng.Init(false, pub8); eng.BlockUpdate(data, 0, data.Length); if (eng.VerifySignature(s)) { Fail("fixed salt failure verfied"); } }
private bool DoVerify( AsymmetricKeyParameter key) { string digestName = Helper.GetDigestAlgName(this.DigestAlgOid); IDigest digest = Helper.GetDigestInstance(digestName); DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.ObjectID; Asn1Encodable sigParams = this.encryptionAlgorithm.Parameters; ISigner sig; if (sigAlgOid.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdRsassaPss)) { // RFC 4056 2.2 // When the id-RSASSA-PSS algorithm identifier is used for a signature, // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params. if (sigParams == null) throw new CmsException("RSASSA-PSS signature must specify algorithm parameters"); try { // TODO Provide abstract configuration mechanism // (via alternate SignerUtilities.GetSigner method taking ASN.1 params) Asn1.Pkcs.RsassaPssParameters pss = Asn1.Pkcs.RsassaPssParameters.GetInstance( sigParams.ToAsn1Object()); if (!pss.HashAlgorithm.ObjectID.Equals(this.digestAlgorithm.ObjectID)) throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm"); if (!pss.MaskGenAlgorithm.ObjectID.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdMgf1)) throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF"); IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.ObjectID); int saltLength = pss.SaltLength.Value.IntValue; byte trailerField = (byte) pss.TrailerField.Value.IntValue; // RFC 4055 3.1 // The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC if (trailerField != 1) throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1"); sig = new PssSigner(new RsaBlindedEngine(), pssDigest, saltLength); } catch (Exception e) { throw new CmsException("failed to set RSASSA-PSS signature parameters", e); } } else { // TODO Probably too strong a check at the moment // if (sigParams != null) // throw new CmsException("unrecognised signature parameters provided"); string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid); sig = Helper.GetSignatureInstance(signatureName); } try { if (digestCalculator != null) { resultDigest = digestCalculator.GetDigest(); } else { if (content != null) { content.Write(new DigOutputStream(digest)); } else if (signedAttributeSet == null) { // TODO Get rid of this exception and just treat content==null as empty not missing? throw new CmsException("data not encapsulated in signature - use detached constructor."); } resultDigest = DigestUtilities.DoFinal(digest); } } catch (IOException e) { throw new CmsException("can't process mime object to create signature.", e); } // TODO Shouldn't be using attribute OID as contentType (should be null) bool isCounterSignature = contentType.Equals(CmsAttributes.CounterSignature); // RFC 3852 11.1 Check the content-type attribute is correct { Asn1Object validContentType = GetSingleValuedSignedAttribute( CmsAttributes.ContentType, "content-type"); if (validContentType == null) { if (!isCounterSignature && signedAttributeSet != null) throw new CmsException("The content-type attribute type MUST be present whenever signed attributes are present in signed-data"); } else { if (isCounterSignature) throw new CmsException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute"); if (!(validContentType is DerObjectIdentifier)) throw new CmsException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'"); DerObjectIdentifier signedContentType = (DerObjectIdentifier)validContentType; if (!signedContentType.Equals(contentType)) throw new CmsException("content-type attribute value does not match eContentType"); } } // RFC 3852 11.2 Check the message-digest attribute is correct { Asn1Object validMessageDigest = GetSingleValuedSignedAttribute( CmsAttributes.MessageDigest, "message-digest"); if (validMessageDigest == null) { if (signedAttributeSet != null) throw new CmsException("the message-digest signed attribute type MUST be present when there are any signed attributes present"); } else { if (!(validMessageDigest is Asn1OctetString)) { throw new CmsException("message-digest attribute value not of ASN.1 type 'OCTET STRING'"); } Asn1OctetString signedMessageDigest = (Asn1OctetString)validMessageDigest; if (!Arrays.AreEqual(resultDigest, signedMessageDigest.GetOctets())) throw new CmsException("message-digest attribute value does not match calculated value"); } } // RFC 3852 11.4 Validate countersignature attribute(s) { Asn1.Cms.AttributeTable signedAttrTable = this.SignedAttributes; if (signedAttrTable != null && signedAttrTable.GetAll(CmsAttributes.CounterSignature).Count > 0) { throw new CmsException("A countersignature attribute MUST NOT be a signed attribute"); } Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes; if (unsignedAttrTable != null) { foreach (Asn1.Cms.Attribute csAttr in unsignedAttrTable.GetAll(CmsAttributes.CounterSignature)) { if (csAttr.AttrValues.Count < 1) throw new CmsException("A countersignature attribute MUST contain at least one AttributeValue"); // Note: We don't recursively validate the countersignature value } } } try { sig.Init(false, key); if (signedAttributeSet == null) { if (digestCalculator != null) { // need to decrypt signature and check message bytes return VerifyDigest(resultDigest, key, this.GetSignature()); } else if (content != null) { // TODO Use raw signature of the hash value instead content.Write(new SigOutputStream(sig)); } } else { byte[] tmp = this.GetEncodedSignedAttributes(); sig.BlockUpdate(tmp, 0, tmp.Length); } return sig.VerifySignature(this.GetSignature()); } catch (InvalidKeyException e) { throw new CmsException("key not appropriate to signature in message.", e); } catch (IOException e) { throw new CmsException("can't process mime object to create signature.", e); } catch (SignatureException e) { throw new CmsException("invalid signature format in message: " + e.Message, e); } }
private bool DoVerify( AsymmetricKeyParameter key, Asn1.Cms.AttributeTable signedAttrTable) { string digestName = Helper.GetDigestAlgName(this.DigestAlgOid); IDigest digest = Helper.GetDigestInstance(digestName); DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.ObjectID; Asn1Encodable sigParams = this.encryptionAlgorithm.Parameters; ISigner sig; if (sigAlgOid.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdRsassaPss)) { // RFC 4056 2.2 // When the id-RSASSA-PSS algorithm identifier is used for a signature, // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params. if (sigParams == null) throw new CmsException("RSASSA-PSS signature must specify algorithm parameters"); try { // TODO Provide abstract configuration mechanism Asn1.Pkcs.RsassaPssParameters pss = Asn1.Pkcs.RsassaPssParameters.GetInstance( sigParams.ToAsn1Object()); if (!pss.HashAlgorithm.ObjectID.Equals(this.digestAlgorithm.ObjectID)) throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm"); if (!pss.MaskGenAlgorithm.ObjectID.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdMgf1)) throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF"); IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.ObjectID); int saltLength = pss.SaltLength.Value.IntValue; byte trailerField = (byte) pss.TrailerField.Value.IntValue; // RFC 4055 3.1 // The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC if (trailerField != 1) throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1"); sig = new PssSigner(new RsaBlindedEngine(), pssDigest, saltLength); } catch (Exception e) { throw new CmsException("failed to set RSASSA-PSS signature parameters", e); } } else { // TODO Probably too strong a check at the moment // if (sigParams != null) // throw new CmsException("unrecognised signature parameters provided"); string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid); sig = Helper.GetSignatureInstance(signatureName); } try { sig.Init(false, key); if (signedAttributes == null) { if (content != null) { content.Write(new CmsSignedDataGenerator.SigOutputStream(sig)); content.Write(new CmsSignedDataGenerator.DigOutputStream(digest)); resultDigest = DigestUtilities.DoFinal(digest); } else { resultDigest = digestCalculator.GetDigest(); // need to decrypt signature and check message bytes return VerifyDigest(resultDigest, key, this.GetSignature()); } } else { byte[] hash; if (content != null) { content.Write( new CmsSignedDataGenerator.DigOutputStream(digest)); hash = DigestUtilities.DoFinal(digest); } else if (digestCalculator != null) { hash = digestCalculator.GetDigest(); } else { hash = null; } resultDigest = hash; Asn1.Cms.Attribute dig = signedAttrTable[Asn1.Cms.CmsAttributes.MessageDigest]; Asn1.Cms.Attribute type = signedAttrTable[Asn1.Cms.CmsAttributes.ContentType]; if (dig == null) { throw new SignatureException("no hash for content found in signed attributes"); } if (type == null && !contentType.Equals(CmsAttributes.CounterSignature)) { throw new SignatureException("no content type id found in signed attributes"); } Asn1Object hashObj = dig.AttrValues[0].ToAsn1Object(); if (hashObj is Asn1OctetString) { byte[] signedHash = ((Asn1OctetString)hashObj).GetOctets(); if (!Arrays.AreEqual(hash, signedHash)) { throw new SignatureException("content hash found in signed attributes different"); } } else if (hashObj is DerNull) { if (hash != null) { throw new SignatureException("NULL hash found in signed attributes when one expected"); } } if (type != null) { DerObjectIdentifier typeOID = (DerObjectIdentifier)type.AttrValues[0]; if (!typeOID.Equals(contentType)) { throw new SignatureException("contentType in signed attributes different"); } } byte[] tmp = this.GetEncodedSignedAttributes(); sig.BlockUpdate(tmp, 0, tmp.Length); } return sig.VerifySignature(this.GetSignature()); } catch (InvalidKeyException e) { throw new CmsException( "key not appropriate to signature in message.", e); } catch (IOException e) { throw new CmsException( "can't process mime object to create signature.", e); } catch (SignatureException e) { throw new CmsException( "invalid signature format in message: " + e.Message, e); } }
public override void PerformTest() { ISigner s = SignerUtilities.GetSigner("SHA1withRSA/PSS"); s.Init(true, new ParametersWithRandom(privKey, new FixedRandom(slt1a))); s.BlockUpdate(msg1a, 0, msg1a.Length); byte[] sig = s.GenerateSignature(); if (!Arrays.AreEqual(sig1a, sig)) { Fail("PSS Sign test expected " + Hex.ToHexString(sig1a) + " got " + Hex.ToHexString(sig)); } s = SignerUtilities.GetSigner("SHA1withRSAandMGF1"); s.Init(false, pubKey); s.BlockUpdate(msg1a, 0, msg1a.Length); if (!s.VerifySignature(sig1a)) { Fail("SHA1 signature verification failed"); } s = SignerUtilities.GetSigner("SHA1withRSAandMGF1"); s.Init(false, pubKey); s.BlockUpdate(msg1a, 0, msg1a.Length); if (!s.VerifySignature(sig1a)) { Fail("SHA1 signature verification with default parameters failed"); } // AlgorithmParameters pss = s.getParameters(); // TODO Can we do some equivalent check? // if (!Arrays.AreEqual(pss.getEncoded(), new byte[] { 0x30, 0x00 })) // { // Fail("failed default encoding test."); // } s = SignerUtilities.GetSigner("SHA256withRSA/PSS"); s.Init(true, new ParametersWithRandom(privKey, new FixedRandom(slt1a))); s.BlockUpdate(msg1a, 0, msg1a.Length); sig = s.GenerateSignature(); if (!Arrays.AreEqual(sig1b, sig)) { Fail("PSS Sign test expected " + Hex.ToHexString(sig1b) + " got " + Hex.ToHexString(sig)); } s = SignerUtilities.GetSigner("SHA256withRSAandMGF1"); s.Init(false, pubKey); s.BlockUpdate(msg1a, 0, msg1a.Length); if (!s.VerifySignature(sig1b)) { Fail("SHA256 signature verification failed"); } // // 512 test -with zero salt length // //s = SignerUtilities.GetSigner("SHA512withRSAandMGF1"); // s.setParameter( // new PSSParameterSpec("SHA-512", "MGF1", new MGF1ParameterSpec("SHA-512"), 0, 1)); // TODO How to do this via SignerUtilities/Init // trailerField=1 above means use default/implicit trailer?) s = new PssSigner(new RsaEngine(), new Sha512Digest(), 0, PssSigner.TrailerImplicit); s.Init(true, privKey); s.BlockUpdate(msg1a, 0, msg1a.Length); sig = s.GenerateSignature(); // pss = s.getParameters(); if (!Arrays.AreEqual(sig1c, sig)) { Fail("PSS Sign test expected " + Hex.ToHexString(sig1c) + " got " + Hex.ToHexString(sig)); } // s = SignerUtilities.GetSigner("SHA512withRSAandMGF1"); // TODO How to do this via SignerUtilities/Init // trailerField=1 above means use default/implicit trailer?) s = new PssSigner(new RsaEngine(), new Sha512Digest(), 0, PssSigner.TrailerImplicit); s.Init(false, pubKey); s.BlockUpdate(msg1a, 0, msg1a.Length); if (!s.VerifySignature(sig1c)) { Fail("SHA512 signature verification failed"); } SecureRandom random = new SecureRandom(); // Note: PSS minimum key size determined by hash/salt lengths // PrivateKey priv2048Key = fact.generatePrivate(RSATest.priv2048KeySpec); // PublicKey pub2048Key = fact.generatePublic(RSATest.pub2048KeySpec); AsymmetricKeyParameter priv2048Key = RsaTest.priv2048KeySpec; AsymmetricKeyParameter pub2048Key = RsaTest.pub2048KeySpec; rawModeTest("SHA1withRSA/PSS", X509ObjectIdentifiers.IdSha1, priv2048Key, pub2048Key, random); // FIXME // rawModeTest("SHA224withRSA/PSS", NistObjectIdentifiers.IdSha224, priv2048Key, pub2048Key, random); // rawModeTest("SHA256withRSA/PSS", NistObjectIdentifiers.IdSha256, priv2048Key, pub2048Key, random); // rawModeTest("SHA384withRSA/PSS", NistObjectIdentifiers.IdSha384, priv2048Key, pub2048Key, random); // rawModeTest("SHA512withRSA/PSS", NistObjectIdentifiers.IdSha512, priv2048Key, pub2048Key, random); }