public 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); }
/** * return true if the value r and s represent a Gost3410 signature for * the passed in message for standard Gost3410 the message should be a * Gost3411 hash of the real message to be verified. */ public bool VerifySignature( byte[] message, BigInteger r, BigInteger s) { byte[] mRev = new byte[message.Length]; // conversion is little-endian for (int i = 0; i != mRev.Length; i++) { mRev[i] = message[mRev.Length - 1 - i]; } BigInteger m = new BigInteger(1, mRev); Gost3410Parameters parameters = key.Parameters; if (r.SignValue < 0 || parameters.Q.CompareTo(r) <= 0) { return false; } if (s.SignValue < 0 || parameters.Q.CompareTo(s) <= 0) { return false; } BigInteger v = m.ModPow(parameters.Q.Subtract(BigInteger.Two), parameters.Q); BigInteger z1 = s.Multiply(v).Mod(parameters.Q); BigInteger z2 = (parameters.Q.Subtract(r)).Multiply(v).Mod(parameters.Q); z1 = parameters.A.ModPow(z1, parameters.P); z2 = ((Gost3410PublicKeyParameters)key).Y.ModPow(z2, parameters.P); BigInteger u = z1.Multiply(z2).Mod(parameters.P).Mod(parameters.Q); return u.Equals(r); }
/** * given a message from a given party and the corresponding public key * calculate the next message in the agreement sequence. In this case * this will represent the shared secret. */ public BigInteger CalculateAgreement( DHPublicKeyParameters pub, BigInteger message) { if (pub == null) throw new ArgumentNullException("pub"); if (message == null) throw new ArgumentNullException("message"); if (!pub.Parameters.Equals(dhParams)) { throw new ArgumentException("Diffie-Hellman public key has wrong parameters."); } BigInteger p = dhParams.P; return message.ModPow(key.X, p).Multiply(pub.Y.ModPow(privateValue, p)).Mod(p); }
/** * Procedure C * procedure generates the a value from the given p,q, * returning the a value. */ private BigInteger procedure_C(BigInteger p, BigInteger q) { BigInteger pSub1 = p.Subtract(BigInteger.One); BigInteger pSub1Divq = pSub1.Divide(q); for(;;) { BigInteger d = new BigInteger(p.BitLength, init_random); // 1 < d < p-1 if (d.CompareTo(BigInteger.One) > 0 && d.CompareTo(pSub1) < 0) { BigInteger a = d.ModPow(pSub1Divq, p); if (a.CompareTo(BigInteger.One) != 0) { return a; } } } }
/** * Process a single block using the basic ElGamal algorithm. * * @param in the input array. * @param inOff the offset into the input buffer where the data starts. * @param length the length of the data to be processed. * @return the result of the ElGamal process. * @exception DataLengthException the input block is too large. */ public byte[] ProcessBlock( byte[] input, int inOff, int length) { if (key == null) throw new InvalidOperationException("ElGamal engine not initialised"); int maxLength = forEncryption ? (bitSize - 1 + 7) / 8 : GetInputBlockSize(); if (length > maxLength) throw new DataLengthException("input too large for ElGamal cipher.\n"); BigInteger p = key.Parameters.P; byte[] output; if (key is ElGamalPrivateKeyParameters) // decryption { int halfLength = length / 2; BigInteger gamma = new BigInteger(1, input, inOff, halfLength); BigInteger phi = new BigInteger(1, input, inOff + halfLength, halfLength); ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters) key; // a shortcut, which generally relies on p being prime amongst other things. // if a problem with this shows up, check the p and g values! BigInteger m = gamma.ModPow(p.Subtract(BigInteger.One).Subtract(priv.X), p).Multiply(phi).Mod(p); output = m.ToByteArrayUnsigned(); } else // encryption { BigInteger tmp = new BigInteger(1, input, inOff, length); if (tmp.BitLength >= p.BitLength) throw new DataLengthException("input too large for ElGamal cipher.\n"); ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters) key; BigInteger pSub2 = p.Subtract(BigInteger.Two); // TODO In theory, a series of 'k', 'g.ModPow(k, p)' and 'y.ModPow(k, p)' can be pre-calculated BigInteger k; do { k = new BigInteger(p.BitLength, random); } while (k.SignValue == 0 || k.CompareTo(pSub2) > 0); BigInteger g = key.Parameters.G; BigInteger gamma = g.ModPow(k, p); BigInteger phi = tmp.Multiply(pub.Y.ModPow(k, p)).Mod(p); output = new byte[this.GetOutputBlockSize()]; // TODO Add methods to allow writing BigInteger to existing byte array? byte[] out1 = gamma.ToByteArrayUnsigned(); byte[] out2 = phi.ToByteArrayUnsigned(); out1.CopyTo(output, output.Length / 2 - out1.Length); out2.CopyTo(output, output.Length - out2.Length); } return output; }
private static BigInteger CalculatePublicKey(BigInteger p, BigInteger g, BigInteger x) { return g.ModPow(x, p); }
protected virtual BigInteger CalculateGenerator_FIPS186_3_Verifiable(IDigest d, BigInteger p, BigInteger q, byte[] seed, int index) { // A.2.3 Verifiable Canonical Generation of the Generator g BigInteger e = p.Subtract(BigInteger.One).Divide(q); byte[] ggen = Hex.Decode("6767656E"); // 7. U = domain_parameter_seed || "ggen" || index || count. byte[] U = new byte[seed.Length + ggen.Length + 1 + 2]; Array.Copy(seed, 0, U, 0, seed.Length); Array.Copy(ggen, 0, U, seed.Length, ggen.Length); U[U.Length - 3] = (byte)index; byte[] w = new byte[d.GetDigestSize()]; for (int count = 1; count < (1 << 16); ++count) { Inc(U); Hash(d, U, w); BigInteger W = new BigInteger(1, w); BigInteger g = W.ModPow(e, p); if (g.CompareTo(BigInteger.Two) >= 0) return g; } return null; }
/** * Set the private key. * * @param p key parameter: field modulus * @param q key parameter: subgroup order * @param g key parameter: generator * @param x private key */ public void setPrivateKey(BigInteger p, BigInteger q, BigInteger g, BigInteger x) { /* * Perform some basic sanity checks. We do not * check primality of p or q because that would * be too expensive. * * We reject keys where q is longer than 999 bits, * because it would complicate signature encoding. * Normal DSA keys do not have a q longer than 256 * bits anyway. */ if(p == null || q == null || g == null || x == null || p.SignValue <= 0 || q.SignValue <= 0 || g.SignValue <= 0 || x.SignValue <= 0 || x.CompareTo(q) >= 0 || q.CompareTo(p) >= 0 || q.BitLength > 999 || g.CompareTo(p) >= 0 || g.BitLength == 1 || g.ModPow(q, p).BitLength != 1) { throw new InvalidOperationException( "invalid DSA private key"); } this.p = p; this.q = q; this.g = g; this.x = x; qlen = q.BitLength; if(q.SignValue <= 0 || qlen < 8) { throw new InvalidOperationException( "bad group order: " + q); } rolen = (qlen + 7) >> 3; rlen = rolen * 8; /* * Convert the private exponent (x) into a sequence * of octets. */ bx = int2octets(x); }