RSA-PSS as described in Pkcs# 1 v 2.1.

Note: the usual value for the salt length is the number of bytes in the hash function.

Inheritance: ISigner
Example #1
0
        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");
            }
        }
Example #2
0
		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);
		}
Example #3
0
        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);
            }
        }
Example #4
0
		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");
			}
		}
Example #5
0
        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");
            }
        }
Example #6
0
		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);
			}
		}
Example #8
0
		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);
		}