private void KDF2Test(int Size, byte[] Salt, byte[] Output) { byte[] outBytes = new byte[Size]; using (KDF2Drbg gen = new KDF2Drbg(new SHA256())) { gen.Initialize(Salt); gen.Generate(outBytes, 0, Size); } if (Compare.AreEqual(outBytes, Output) == false) throw new Exception("PBKDF2: Values are not equal! Expected: " + HexConverter.ToString(Output) + " Received: " + HexConverter.ToString(outBytes)); }
/// <summary> /// Encrypt a plain text message /// </summary> /// /// <param name="Input">The plain text</param> /// /// <returns>The cipher text</returns> public byte[] Encrypt(byte[] Input) { if (!_isEncryption) throw new CryptoAsymmetricSignException("KobaraImaiCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException()); int c2Len = _dgtEngine.DigestSize; int c4Len = _K >> 3; int c5Len = (BigMath.Binomial(_N, _T).BitLength - 1) >> 3; int mLen = c4Len + c5Len - c2Len - MPKCINFO.Length; if (Input.Length > mLen) mLen = Input.Length; int c1Len = mLen + MPKCINFO.Length; int c6Len = c1Len + c2Len - c4Len - c5Len; // compute (m||const) byte[] mConst = new byte[c1Len]; Array.Copy(Input, 0, mConst, 0, Input.Length); Array.Copy(MPKCINFO, 0, mConst, mLen, MPKCINFO.Length); // generate random r of length c2Len bytes byte[] r = new byte[c2Len]; _rndEngine.GetBytes(r); byte[] c1; // get PRNG object ToDo: //DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest()); //why bc, why? using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest))) { // seed PRNG with r' sr0.Initialize(r); // generate random sequence ... c1 = new byte[c1Len]; sr0.Generate(c1); } // ... and XOR with (m||const) to obtain c1 for (int i = c1Len - 1; i >= 0; i--) c1[i] ^= mConst[i]; // compute H(c1) ... byte[] c2 = new byte[_dgtEngine.DigestSize]; _dgtEngine.BlockUpdate(c1, 0, c1.Length); _dgtEngine.DoFinal(c2, 0); // ... and XOR with r for (int i = c2Len - 1; i >= 0; i--) c2[i] ^= r[i]; // compute (c2||c1) byte[] c2c1 = ByteUtils.Concatenate(c2, c1); // split (c2||c1) into (c6||c5||c4), where c4Len is k/8 bytes, c5Len is // floor[log(n|t)]/8 bytes, and c6Len is c1Len+c2Len-c4Len-c5Len (may be 0). byte[] c6 = new byte[0]; if (c6Len > 0) { c6 = new byte[c6Len]; Array.Copy(c2c1, 0, c6, 0, c6Len); } byte[] c5 = new byte[c5Len]; Array.Copy(c2c1, c6Len, c5, 0, c5Len); byte[] c4 = new byte[c4Len]; Array.Copy(c2c1, c6Len + c5Len, c4, 0, c4Len); // convert c4 to vector over GF(2) GF2Vector c4Vec = GF2Vector.OS2VP(_K, c4); // convert c5 to error vector z GF2Vector z = CCA2Conversions.Encode(_N, _T, c5); // compute encC4 = E(c4, z) byte[] encC4 = CCA2Primitives.Encrypt((MPKCPublicKey)_asmKey, c4Vec, z).GetEncoded(); // if c6Len > 0 return (c6||encC4) if (c6Len > 0) return ByteUtils.Concatenate(c6, encC4); // else, return encC4 return encC4; }
/// <summary> /// Decrypt a cipher text /// </summary> /// /// <param name="Input">The cipher text</param> /// /// <returns>The plain text</returns> public byte[] Decrypt(byte[] Input) { if (_isEncryption) throw new CryptoAsymmetricSignException("KobaraImaiCipher:Decrypt", "The cipher is not initialized for decryption!", new ArgumentException()); int nDiv8 = _N >> 3; if (Input.Length < nDiv8) throw new CryptoAsymmetricSignException("KobaraImaiCipher:Decrypt", "Bad Padding: Ciphertext too short!", new ArgumentException()); int c2Len = _dgtEngine.DigestSize; int c4Len = _K >> 3; int c6Len = Input.Length - nDiv8; // split cipher text (c6||encC4), where c6 may be empty byte[] c6, encC4; if (c6Len > 0) { byte[][] c6EncC4 = ByteUtils.Split(Input, c6Len); c6 = c6EncC4[0]; encC4 = c6EncC4[1]; } else { c6 = new byte[0]; encC4 = Input; } // convert encC4 into vector over GF(2) GF2Vector encC4Vec = GF2Vector.OS2VP(_N, encC4); // decrypt encC4Vec to obtain c4 and error vector z GF2Vector[] c4z = CCA2Primitives.Decrypt((MPKCPrivateKey)_asmKey, encC4Vec); byte[] c4 = c4z[0].GetEncoded(); GF2Vector z = c4z[1]; // if length of c4 is greater than c4Len (because of padding), truncate the padding bytes if (c4.Length > c4Len) c4 = ByteUtils.SubArray(c4, 0, c4Len); // compute c5 = Conv^-1(z) byte[] c5 = CCA2Conversions.Decode(_N, _T, z); // compute (c6||c5||c4) byte[] c6c5c4 = ByteUtils.Concatenate(c6, c5); c6c5c4 = ByteUtils.Concatenate(c6c5c4, c4); // split (c6||c5||c4) into (c2||c1), where c2Len = mdLen and c1Len = input.length-c2Len bytes. int c1Len = c6c5c4.Length - c2Len; byte[][] c2c1 = ByteUtils.Split(c6c5c4, c2Len); byte[] c2 = c2c1[0]; byte[] c1 = c2c1[1]; // compute H(c1) ... byte[] rPrime = new byte[_dgtEngine.DigestSize]; _dgtEngine.BlockUpdate(c1, 0, c1.Length); _dgtEngine.DoFinal(rPrime, 0); // ... and XOR with c2 to obtain r' for (int i = c2Len - 1; i >= 0; i--) rPrime[i] ^= c2[i]; byte[] mConstPrime; // get PRNG object using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest))) { // seed PRNG with r' sr0.Initialize(rPrime); // generate random sequence R(r') ... mConstPrime = new byte[c1Len]; sr0.Generate(mConstPrime); } // ... and XOR with c1 to obtain (m||const') for (int i = c1Len - 1; i >= 0; i--) mConstPrime[i] ^= c1[i]; if (mConstPrime.Length < c1Len) throw new CryptoAsymmetricSignException("KobaraImaiCipher:Decrypt", "Bad Padding: invalid ciphertext!", new ArgumentException()); byte[][] temp = ByteUtils.Split(mConstPrime, c1Len - MPKCINFO.Length); byte[] mr = temp[0]; byte[] constPrime = temp[1]; if (!ByteUtils.Equals(constPrime, MPKCINFO)) throw new CryptoAsymmetricSignException("KobaraImaiCipher:Decrypt", "Bad Padding: invalid ciphertext!", new ArgumentException()); return mr; }
/// <summary> /// Decrypt a cipher text /// </summary> /// /// <param name="Input">The cipher text</param> /// /// <returns>The plain text</returns> public byte[] Decrypt(byte[] Input) { if (_isEncryption) throw new CryptoAsymmetricSignException("FujisakiCipher:Decrypt", "The cipher is not initialized for decryption!", new ArgumentException()); int c1Len = (_N + 7) >> 3; int c2Len = Input.Length - c1Len; // split ciphertext (c1||c2) byte[][] c1c2 = ByteUtils.Split(Input, c1Len); byte[] c1 = c1c2[0]; byte[] c2 = c1c2[1]; // decrypt c1 ... GF2Vector hrmVec = GF2Vector.OS2VP(_N, c1); GF2Vector[] decC1 = CCA2Primitives.Decrypt((MPKCPrivateKey)_asmKey, hrmVec); byte[] rBytes = decC1[0].GetEncoded(); // ... and obtain error vector z GF2Vector z = decC1[1]; byte[] mBytes; // get PRNG object.. using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest))) { // seed PRNG with r' sr0.Initialize(rBytes); // generate random sequence mBytes = new byte[c2Len]; sr0.Generate(mBytes); } // XOR with c2 to obtain m for (int i = 0; i < c2Len; i++) mBytes[i] ^= c2[i]; // compute H(r||m) byte[] rmBytes = ByteUtils.Concatenate(rBytes, mBytes); byte[] hrm = new byte[_dgtEngine.DigestSize]; _dgtEngine.BlockUpdate(rmBytes, 0, rmBytes.Length); _dgtEngine.DoFinal(hrm, 0); // compute Conv(H(r||m)) hrmVec = CCA2Conversions.Encode(_N, _T, hrm); // check that Conv(H(m||r)) = z if (!hrmVec.Equals(z)) throw new CryptoAsymmetricSignException("FujisakiCipher:Decrypt", "Bad Padding: invalid ciphertext!", new InvalidDataException()); // return plaintext m return mBytes; }
/// <summary> /// Encrypt a plain text message /// </summary> /// /// <param name="Input">The plain text</param> /// /// <returns>The cipher text</returns> public byte[] Encrypt(byte[] Input) { if (!_isEncryption) throw new CryptoAsymmetricSignException("FujisakiCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException()); // generate random vector r of length k bits GF2Vector r = new GF2Vector(_K, _rndEngine); // convert r to byte array byte[] rBytes = r.GetEncoded(); // compute (r||input) byte[] rm = ByteUtils.Concatenate(rBytes, Input); // compute H(r||input) _dgtEngine.BlockUpdate(rm, 0, rm.Length); byte[] hrm = new byte[_dgtEngine.DigestSize]; _dgtEngine.DoFinal(hrm, 0); // convert H(r||input) to error vector z GF2Vector z = CCA2Conversions.Encode(_N, _T, hrm); // compute c1 = E(r, z) byte[] c1 = CCA2Primitives.Encrypt((MPKCPublicKey)_asmKey, r, z).GetEncoded(); byte[] c2; // get PRNG object using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest))) { // seed PRNG with r' sr0.Initialize(rBytes); // generate random c2 c2 = new byte[Input.Length]; sr0.Generate(c2); } // XOR with input for (int i = 0; i < Input.Length; i++) c2[i] ^= Input[i]; // return (c1||c2) return ByteUtils.Concatenate(c1, c2); }
/// <summary> /// Encrypt a plain text message /// </summary> /// /// <param name="Input">The plain text</param> /// /// <returns>The cipher text</returns> public byte[] Encrypt(byte[] Input) { // generate random vector r of length k bits GF2Vector r = new GF2Vector(_K, _secRnd); // convert r to byte array byte[] rBytes = r.GetEncoded(); // compute (r||input) byte[] rm = ByteUtils.Concatenate(rBytes, Input); // compute H(r||input) _dgtEngine.BlockUpdate(rm, 0, rm.Length); byte[] hrm = new byte[_dgtEngine.DigestSize]; _dgtEngine.DoFinal(hrm, 0); // convert H(r||input) to error vector z GF2Vector z = CCA2Conversions.Encode(_N, _T, hrm); // compute c1 = E(r, z) byte[] c1 = CCA2Primitives.Encrypt((MPKCPublicKey)_keyPair.PublicKey, r, z).GetEncoded(); byte[] c2; // get PRNG object using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cipherParams.Digest))) { // seed PRNG with r' sr0.Initialize(rBytes); // generate random c2 c2 = new byte[Input.Length]; sr0.Generate(c2); } // XOR with input for (int i = 0; i < Input.Length; i++) c2[i] ^= Input[i]; // return (c1||c2) return ByteUtils.Concatenate(c1, c2); }
public byte[] Decrypt(byte[] Input) { if (_isEncryption) throw new CryptoAsymmetricSignException("PointchevalCipher:Decrypt", "The cipher is not initialized for decryption!", new ArgumentException()); int c1Len = (_N + 7) >> 3; int c2Len = Input.Length - c1Len; // split cipher text (c1||c2) byte[][] c1c2 = ByteUtils.Split(Input, c1Len); byte[] c1 = c1c2[0]; byte[] c2 = c1c2[1]; // decrypt c1 ... GF2Vector c1Vec = GF2Vector.OS2VP(_N, c1); GF2Vector[] c1Dec = CCA2Primitives.Decrypt((MPKCPrivateKey)_asmKey, c1Vec); byte[] rPrimeBytes = c1Dec[0].GetEncoded(); // ... and obtain error vector z GF2Vector z = c1Dec[1]; byte[] mrBytes; // get PRNG object using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest))) { // seed PRNG with r' sr0.Initialize(rPrimeBytes); // generate random sequence mrBytes = new byte[c2Len]; sr0.Generate(mrBytes); } // XOR with c2 to obtain (m||r) for (int i = 0; i < c2Len; i++) mrBytes[i] ^= c2[i]; // compute H(m||r) _dgtEngine.BlockUpdate(mrBytes, 0, mrBytes.Length); byte[] hmr = new byte[_dgtEngine.DigestSize]; _dgtEngine.DoFinal(hmr, 0); // compute Conv(H(m||r)) c1Vec = CCA2Conversions.Encode(_N, _T, hmr); // check that Conv(H(m||r)) = z if (!c1Vec.Equals(z)) throw new CryptoAsymmetricSignException("PointchevalCipher:Decrypt", "Bad Padding: Invalid ciphertext!", new ArgumentException()); // split (m||r) to obtain m int kDiv8 = _K >> 3; byte[][] mr = ByteUtils.Split(mrBytes, c2Len - kDiv8); // return plain text m return mr[0]; }
public byte[] Encrypt(byte[] Input) { if (!_isEncryption) throw new CryptoAsymmetricSignException("PointchevalCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException()); int kDiv8 = _K >> 3; // generate random r of length k div 8 bytes byte[] r = new byte[kDiv8]; _rndEngine.GetBytes(r); // generate random vector r' of length k bits GF2Vector rPrime = new GF2Vector(_K, _rndEngine); // convert r' to byte array byte[] rPrimeBytes = rPrime.GetEncoded(); // compute (input||r) byte[] mr = ByteUtils.Concatenate(Input, r); // compute H(input||r) _dgtEngine.BlockUpdate(mr, 0, mr.Length); byte[] hmr = new byte[_dgtEngine.DigestSize]; _dgtEngine.DoFinal(hmr, 0); // convert H(input||r) to error vector z GF2Vector z = CCA2Conversions.Encode(_N, _T, hmr); // compute c1 = E(rPrime, z) byte[] c1 = CCA2Primitives.Encrypt((MPKCPublicKey)_asmKey, rPrime, z).GetEncoded(); byte[] c2; // get PRNG object using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest))) { // seed PRNG with r' sr0.Initialize(rPrimeBytes); // generate random c2 c2 = new byte[Input.Length + kDiv8]; sr0.Generate(c2); } // XOR with input for (int i = 0; i < Input.Length; i++) c2[i] ^= Input[i]; // XOR with r for (int i = 0; i < kDiv8; i++) c2[Input.Length + i] ^= r[i]; // return (c1||c2) return ByteUtils.Concatenate(c1, c2); }