/* * Finds a pair of prime BigInteger's {p, q: p = 2q + 1} * * (see: Handbook of Applied Cryptography 4.86) */ internal static BigInteger[] GenerateSafePrimes(int size, int certainty, SecureRandom random) { BigInteger p, q; int qLength = size - 1; int minWeight = size >> 2; if (size <= 32) { for (;;) { q = new BigInteger(qLength, 2, random); p = q.ShiftLeft(1).Add(BigInteger.One); if (!p.IsProbablePrime(certainty)) continue; if (certainty > 2 && !q.IsProbablePrime(certainty - 2)) continue; break; } } else { // Note: Modified from Java version for speed for (;;) { q = new BigInteger(qLength, 0, random); retry: for (int i = 0; i < primeLists.Length; ++i) { int test = q.Remainder(BigPrimeProducts[i]).IntValue; if (i == 0) { int rem3 = test % 3; if (rem3 != 2) { int diff = 2 * rem3 + 2; q = q.Add(BigInteger.ValueOf(diff)); test = (test + diff) % primeProducts[i]; } } int[] primeList = primeLists[i]; for (int j = 0; j < primeList.Length; ++j) { int prime = primeList[j]; int qRem = test % prime; if (qRem == 0 || qRem == (prime >> 1)) { q = q.Add(Six); goto retry; } } } if (q.BitLength != qLength) continue; if (!q.RabinMillerTest(2, random)) continue; p = q.ShiftLeft(1).Add(BigInteger.One); if (!p.RabinMillerTest(certainty, random)) continue; if (certainty > 2 && !q.RabinMillerTest(certainty - 2, random)) continue; /* * Require a minimum weight of the NAF representation, since low-weight primes may be * weak against a version of the number-field-sieve for the discrete-logarithm-problem. * * See "The number field sieve for integers of low weight", Oliver Schirokauer. */ if (WNafUtilities.GetNafWeight(p) < minWeight) continue; break; } } return new BigInteger[] { p, q }; }
public virtual BigInteger ProcessBlock( BigInteger input) { if (key is RsaPrivateCrtKeyParameters) { // // we have the extra factors, use the Chinese Remainder Theorem - the author // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for // advice regarding the expression of this. // RsaPrivateCrtKeyParameters crtKey = (RsaPrivateCrtKeyParameters)key; BigInteger p = crtKey.P; BigInteger q = crtKey.Q; BigInteger dP = crtKey.DP; BigInteger dQ = crtKey.DQ; BigInteger qInv = crtKey.QInv; BigInteger mP, mQ, h, m; // mP = ((input Mod p) ^ dP)) Mod p mP = (input.Remainder(p)).ModPow(dP, p); // mQ = ((input Mod q) ^ dQ)) Mod q mQ = (input.Remainder(q)).ModPow(dQ, q); // h = qInv * (mP - mQ) Mod p h = mP.Subtract(mQ); h = h.Multiply(qInv); h = h.Mod(p); // Mod (in Java) returns the positive residual // m = h * q + mQ m = h.Multiply(q); m = m.Add(mQ); return m; } return input.ModPow(key.Exponent, key.Modulus); }
/* * Finds a pair of prime BigInteger's {p, q: p = 2q + 1} * * (see: Handbook of Applied Cryptography 4.86) */ internal static BigInteger[] GenerateSafePrimes(int size, int certainty, SecureRandom random) { BigInteger p, q; int qLength = size - 1; if (size <= 32) { for (;;) { q = new BigInteger(qLength, 2, random); p = q.ShiftLeft(1).Add(BigInteger.One); if (p.IsProbablePrime(certainty) && (certainty <= 2 || q.IsProbablePrime(certainty))) break; } } else { // Note: Modified from Java version for speed for (;;) { q = new BigInteger(qLength, 0, random); retry: for (int i = 0; i < primeLists.Length; ++i) { int test = q.Remainder(BigPrimeProducts[i]).IntValue; if (i == 0) { int rem3 = test % 3; if (rem3 != 2) { int diff = 2 * rem3 + 2; q = q.Add(BigInteger.ValueOf(diff)); test = (test + diff) % primeProducts[i]; } } int[] primeList = primeLists[i]; for (int j = 0; j < primeList.Length; ++j) { int prime = primeList[j]; int qRem = test % prime; if (qRem == 0 || qRem == (prime >> 1)) { q = q.Add(Six); goto retry; } } } if (q.BitLength != qLength) continue; if (!q.RabinMillerTest(2, random)) continue; p = q.ShiftLeft(1).Add(BigInteger.One); if (p.RabinMillerTest(certainty, random) && (certainty <= 2 || q.RabinMillerTest(certainty - 2, random))) break; } } return new BigInteger[] { p, q }; }
/// <summary> /// reads private key portion of OpenSSH formatted key blob from stream and /// creates a key pair /// </summary> /// <returns>key pair</returns> /// <remarks> /// intended to be called immediately after ParseSsh2PublicKeyData /// </remarks> public AsymmetricCipherKeyPair ReadSsh2KeyData( AsymmetricKeyParameter publicKeyParameter) { if (publicKeyParameter is RsaKeyParameters) { var rsaD = new BigInteger(1, ReadBlob()); var rsaIQMP = new BigInteger(1, ReadBlob()); var rsaP = new BigInteger(1, ReadBlob()); var rsaQ = new BigInteger(1, ReadBlob()); /* compute missing parameters */ var rsaDP = rsaD.Remainder(rsaP.Subtract(BigInteger.One)); var rsaDQ = rsaD.Remainder(rsaQ.Subtract(BigInteger.One)); var rsaPublicKeyParams = publicKeyParameter as RsaKeyParameters; var rsaPrivateKeyParams = new RsaPrivateCrtKeyParameters( rsaPublicKeyParams.Modulus, rsaPublicKeyParams.Exponent, rsaD, rsaP, rsaQ, rsaDP, rsaDQ, rsaIQMP); return new AsymmetricCipherKeyPair(rsaPublicKeyParams, rsaPrivateKeyParams); } else if (publicKeyParameter is DsaPublicKeyParameters) { var dsaX = new BigInteger(1, ReadBlob()); // private key var dsaPublicKeyParams = publicKeyParameter as DsaPublicKeyParameters; DsaPrivateKeyParameters dsaPrivateKeyParams = new DsaPrivateKeyParameters(dsaX, dsaPublicKeyParams.Parameters); return new AsymmetricCipherKeyPair(dsaPublicKeyParams, dsaPrivateKeyParams); } else if (publicKeyParameter is ECPublicKeyParameters) { var ecdsaPrivate = new BigInteger(1, ReadBlob()); var ecPublicKeyParams = publicKeyParameter as ECPublicKeyParameters; ECPrivateKeyParameters ecPrivateKeyParams = new ECPrivateKeyParameters(ecdsaPrivate, ecPublicKeyParams.Parameters); return new AsymmetricCipherKeyPair(ecPublicKeyParams, ecPrivateKeyParams); } else if (publicKeyParameter is Ed25519PublicKeyParameter) { var ed25519Signature = ReadBlob(); var ed25519PrivateKey = new Ed25519PrivateKeyParameter(ed25519Signature); return new AsymmetricCipherKeyPair(publicKeyParameter, ed25519PrivateKey); } else { // unsupported encryption algorithm throw new Exception("Unsupported algorithm"); } }
/// <summary> /// reads private key portion of OpenSSH ssh1 formatted key blob from stream and /// creates a key pair /// </summary> /// <returns>key pair</returns> /// <remarks> /// intended to be called immediately after ParseSsh1PublicKeyData /// </remarks> public AsymmetricCipherKeyPair ReadSsh1KeyData( AsymmetricKeyParameter publicKeyParameter) { var rsa_d = ReadSsh1BigIntBlob(); var rsa_iqmp = ReadSsh1BigIntBlob(); var rsa_q = ReadSsh1BigIntBlob(); var rsa_p = ReadSsh1BigIntBlob(); var rsaD = new BigInteger(1, rsa_d); var rsaIQMP = new BigInteger(1, rsa_iqmp); var rsaP = new BigInteger(1, rsa_p); var rsaQ = new BigInteger(1, rsa_q); var rsaDP = rsaD.Remainder(rsaP.Subtract(BigInteger.One)); var rsaDQ = rsaD.Remainder(rsaQ.Subtract(BigInteger.One)); var rsaPublicKeyParams = publicKeyParameter as RsaKeyParameters; var rsaPrivateKeyParams = new RsaPrivateCrtKeyParameters(rsaPublicKeyParams.Modulus, rsaPublicKeyParams.Exponent, rsaD, rsaP, rsaQ, rsaDP, rsaDQ, rsaIQMP); return new AsymmetricCipherKeyPair(rsaPublicKeyParams, rsaPrivateKeyParams); }
private static AsymmetricCipherKeyPair CreateCipherKeyPair( PublicKeyAlgorithm algorithm, byte[] publicKeyBlob, byte[] privateKeyBlob) { var parser = new BlobParser(publicKeyBlob); var publicKey = parser.ReadSsh2PublicKeyData(); parser = new BlobParser(privateKeyBlob); switch (algorithm) { case PublicKeyAlgorithm.SSH_RSA: var rsaPublicKeyParams = (RsaKeyParameters)publicKey; var d = new BigInteger(1, parser.ReadBlob()); var p = new BigInteger(1, parser.ReadBlob()); var q = new BigInteger(1, parser.ReadBlob()); var inverseQ = new BigInteger(1, parser.ReadBlob()); /* compute missing parameters */ var dp = d.Remainder(p.Subtract(BigInteger.One)); var dq = d.Remainder(q.Subtract(BigInteger.One)); RsaPrivateCrtKeyParameters rsaPrivateKeyParams = new RsaPrivateCrtKeyParameters(rsaPublicKeyParams.Modulus, rsaPublicKeyParams.Exponent, d, p, q, dp, dq, inverseQ); return new AsymmetricCipherKeyPair(rsaPublicKeyParams, rsaPrivateKeyParams); case PublicKeyAlgorithm.SSH_DSS: var dsaPublicKeyParams = (DsaPublicKeyParameters)publicKey; var x = new BigInteger(1, parser.ReadBlob()); DsaPrivateKeyParameters dsaPrivateKeyParams = new DsaPrivateKeyParameters(x, dsaPublicKeyParams.Parameters); return new AsymmetricCipherKeyPair(dsaPublicKeyParams, dsaPrivateKeyParams); case PublicKeyAlgorithm.ED25519: var ed25596PublicKey = (Ed25519PublicKeyParameter)publicKey; byte[] privBlob = parser.ReadBlob(); byte[] privSig = new byte[64]; // OpenSSH's "private key" is actually the private key with the public key tacked on ... Array.Copy(privBlob, 0, privSig, 0, 32); Array.Copy(ed25596PublicKey.Key, 0, privSig, 32, 32); var ed25596PrivateKey = new Ed25519PrivateKeyParameter(privSig); return new AsymmetricCipherKeyPair(ed25596PublicKey, ed25596PrivateKey); case PublicKeyAlgorithm.ECDSA_SHA2_NISTP256: case PublicKeyAlgorithm.ECDSA_SHA2_NISTP384: case PublicKeyAlgorithm.ECDSA_SHA2_NISTP521: var ecPublicKeyParams = (ECPublicKeyParameters)publicKey; var ecdsaPrivate = new BigInteger(1, parser.ReadBlob()); ECPrivateKeyParameters ecPrivateKeyParams = new ECPrivateKeyParameters(ecdsaPrivate, ecPublicKeyParams.Parameters); return new AsymmetricCipherKeyPair(ecPublicKeyParams, ecPrivateKeyParams); default: // unsupported encryption algorithm throw new PpkFormatterException(PpkFormatterException.PpkErrorType.PublicKeyEncryption); } }
/// <summary> /// Finds a pair of prime BigInteger's {p, q: p = 2q + 1} /// /// (see: Handbook of Applied Cryptography 4.86) /// </summary> /// <param name="size">The size.</param> /// <param name="certainty">The certainty.</param> /// <param name="random">The random.</param> /// <returns></returns> internal static IBigInteger[] GenerateSafePrimes(int size, int certainty, ISecureRandom random) { IBigInteger p, q; var qLength = size - 1; if (size <= 32) { for (; ; ) { q = new BigInteger(qLength, 2, random); p = q.ShiftLeft(1).Add(BigInteger.One); if (p.IsProbablePrime(certainty) && (certainty <= 2 || q.IsProbablePrime(certainty))) break; } } else { // Note: Modified from Java version for speed for (; ; ) { q = new BigInteger(qLength, 0, random); retry: for (var i = 0; i < _primeLists.Length; ++i) { var test = q.Remainder(_primeProductsBigs[i]).IntValue; if (i == 0) { var rem3 = test % 3; if (rem3 != 2) { var diff = 2 * rem3 + 2; q = q.Add(BigInteger.ValueOf(diff)); test = (test + diff) % _primeProductsInts[i]; } } var primeList = _primeLists[i]; foreach (var prime in primeList) { var qRem = test % prime; if (qRem != 0 && qRem != (prime >> 1)) continue; q = q.Add(_six); goto retry; } } if (q.BitLength != qLength) continue; if (!((BigInteger)q).RabinMillerTest(2, random)) continue; p = q.ShiftLeft(1).Add(BigInteger.One); if (((BigInteger)p).RabinMillerTest(certainty, random) && (certainty <= 2 || ((BigInteger)q).RabinMillerTest(certainty - 2, random))) break; } } return new[] { p, q }; }