public override byte[] EncryptValue( byte[] rgb ) { if ( m_disposed ) throw new ObjectDisposedException("public key"); if ( !keypairGenerated ) GenerateKeyPair(); BigInteger input = new BigInteger(rgb); BigInteger output = input.ModPow(e, n); byte[] result = output.GetBytes(); // zeroize value input.Clear(); output.Clear(); return result; }
public override byte[] DecryptValue( byte[] rgb ) { if ( m_disposed ) throw new ObjectDisposedException("private key"); // decrypt operation is used for signature if ( !keypairGenerated ) GenerateKeyPair(); BigInteger input = new BigInteger(rgb); BigInteger r = null; // we use key blinding (by default) against timing attacks if ( keyBlinding ) { // x = (r^e * g) mod n // *new* random number (so it's timing is also random) r = BigInteger.GenerateRandom(n.BitCount()); input = r.ModPow(e, n) * input % n; } BigInteger output; // decrypt (which uses the private key) can be // optimized by using CRT (Chinese Remainder Theorem) if ( isCRTpossible ) { // m1 = c^dp mod p BigInteger m1 = input.ModPow(dp, p); // m2 = c^dq mod q BigInteger m2 = input.ModPow(dq, q); BigInteger h; if ( m2 > m1 ) { // thanks to benm! h = p - ( ( m2 - m1 ) * qInv % p ); output = m2 + q * h; } else { // h = (m1 - m2) * qInv mod p h = ( m1 - m2 ) * qInv % p; // m = m2 + q * h; output = m2 + q * h; } } else { // m = c^i mod n output = input.ModPow(d, n); } if ( keyBlinding ) { // Complete blinding // x^e / r mod n output = output * r.ModInverse(n) % n; r.Clear(); } byte[] result = output.GetBytes(); // zeroize values input.Clear(); output.Clear(); return result; }