public void AppliedCryptographySanityChecks()
 {
     // Sanity checks from Applied Cryptography, 2nd Edition p467 - 468
     var p = new BigInteger(47);
     var q = new BigInteger(71);
     var n = p * q;
     var e = new BigInteger(79);
     var d = e.ModInverse((p - 1) * (q - 1));
     Func<int, string> encryptor = m => (new BigInteger(m).ModPow(e, n)).ToString();
     Assert.AreEqual("1570", encryptor(688));
     Assert.AreEqual("2756", encryptor(232));
     Assert.AreEqual("2091", encryptor(687));
     Assert.AreEqual("2276", encryptor(966));
     Assert.AreEqual("2423", encryptor(668));
     Assert.AreEqual("158", encryptor(3));            
 }
Example #2
0
		public override bool VerifySignature (byte[] rgbHash, byte[] rgbSignature) 
		{
			if (m_disposed)
				throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));

			if (rgbHash == null)
				throw new ArgumentNullException ("rgbHash");
			if (rgbSignature == null)
				throw new ArgumentNullException ("rgbSignature");

			if (rgbHash.Length != 20)
				throw new CryptographicException ("invalid hash length");
			// signature is always 40 bytes (no matter the size of the
			// public key). In fact it is 2 times the size of the private
			// key (which is 20 bytes for 512 to 1024 bits DSA keypairs)
			if (rgbSignature.Length != 40)
				throw new CryptographicException ("invalid signature length");

			// it would be stupid to verify a signature with a newly
			// generated keypair - so we return false
			if (!keypairGenerated)
				return false;

			try {
				BigInteger m = new BigInteger (rgbHash);
				byte[] half = new byte [20];
				Array.Copy (rgbSignature, 0, half, 0, 20);
				BigInteger r = new BigInteger (half);
				Array.Copy (rgbSignature, 20, half, 0, 20);
				BigInteger s = new BigInteger (half);

				if ((r < 0) || (q <= r))
					return false;

				if ((s < 0) || (q <= s))
					return false;

				BigInteger w = s.ModInverse(q);
				BigInteger u1 = m * w % q;
				BigInteger u2 = r * w % q;

				u1 = g.ModPow(u1, p);
				u2 = y.ModPow(u2, p);

				BigInteger v = ((u1 * u2 % p) % q);
				return (v == r);
			}
			catch {
				throw new CryptographicException ("couldn't compute signature verification");
			}
		}
Example #3
0
		private void GenerateKeyPair () 
		{
			// p and q values should have a length of half the strength in bits
			int pbitlength = ((KeySize + 1) >> 1);
			int qbitlength = (KeySize - pbitlength);
			const uint uint_e = 17;
			e = uint_e; // fixed
	
			// generate p, prime and (p-1) relatively prime to e
			for (;;) {
				p = BigInteger.GeneratePseudoPrime (pbitlength);
				if (p % uint_e != 1)
					break;
			}
			// generate a modulus of the required length
			for (;;) {
				// generate q, prime and (q-1) relatively prime to e,
				// and not equal to p
				for (;;) {
					q = BigInteger.GeneratePseudoPrime (qbitlength);
					if ((q % uint_e != 1) && (p != q))
						break;
				}
	
				// calculate the modulus
				n = p * q;
				if (n.BitCount () == KeySize)
					break;
	
				// if we get here our primes aren't big enough, make the largest
				// of the two p and try again
				if (p < q)
					p = q;
			}
	
			BigInteger pSub1 = (p - 1);
			BigInteger qSub1 = (q - 1);
			BigInteger phi = pSub1 * qSub1;
	
			// calculate the private exponent
			d = e.ModInverse (phi);
	
			// calculate the CRT factors
			dp = d % pSub1;
			dq = d % qSub1;
			qInv = q.ModInverse (p);
	
			keypairGenerated = true;
			isCRTpossible = true;

			if (KeyGenerated != null)
				KeyGenerated (this, null);
		}
Example #4
0
		public override void ImportParameters (RSAParameters parameters) 
		{
			if (m_disposed)
				throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));

			// if missing "mandatory" parameters
			if (parameters.Exponent == null) 
				throw new CryptographicException (Locale.GetText ("Missing Exponent"));
			if (parameters.Modulus == null)
				throw new CryptographicException (Locale.GetText ("Missing Modulus"));
	
			e = new BigInteger (parameters.Exponent);
			n = new BigInteger (parameters.Modulus);
			// only if the private key is present
			if (parameters.D != null)
				d = new BigInteger (parameters.D);
			if (parameters.DP != null)
				dp = new BigInteger (parameters.DP);
			if (parameters.DQ != null)
				dq = new BigInteger (parameters.DQ);
			if (parameters.InverseQ != null)
				qInv = new BigInteger (parameters.InverseQ);
			if (parameters.P != null)
				p = new BigInteger (parameters.P);
			if (parameters.Q != null)
				q = new BigInteger (parameters.Q);

			// we now have a keypair
			keypairGenerated = true;
			bool privateKey = ((p != null) && (q != null) && (dp != null));
			isCRTpossible = (privateKey && (dq != null) && (qInv != null));

			// check if the public/private keys match
			// the way the check is made allows a bad D to work if CRT is available (like MS does, see unit tests)
			if (!privateKey)
				return;

			// always check n == p * q
			bool ok = (n == (p * q));
			if (ok) {
				// we now know that p and q are correct, so (p - 1), (q - 1) and phi will be ok too
				BigInteger pSub1 = (p - 1);
				BigInteger qSub1 = (q - 1);
				BigInteger phi = pSub1 * qSub1;
				// e is fairly static but anyway we can ensure it makes sense by recomputing d
				BigInteger dcheck = e.ModInverse (phi);

				// now if our new d(check) is different than the d we're provided then we cannot
				// be sure if 'd' or 'e' is invalid... (note that, from experience, 'd' is more 
				// likely to be invalid since it's twice as large as DP (or DQ) and sits at the
				// end of the structure (e.g. truncation).
				ok = (d == dcheck);

				// ... unless we have the pre-computed CRT parameters
				if (!ok && isCRTpossible) {
					// we can override the previous decision since Mono always prefer, for 
					// performance reasons, using the CRT algorithm
					ok = (dp == (dcheck % pSub1)) && (dq == (dcheck % qSub1)) && 
						(qInv == q.ModInverse (p));
				}
			}

			if (!ok)
				throw new CryptographicException (Locale.GetText ("Private/public key mismatch"));
		}