/// <summary> /// Decrypt a cipher text /// </summary> /// /// <param name="Input">The cipher text</param> /// /// <returns>The plain text</returns> public byte[] Decrypt(byte[] Input) { if (m_isEncryption) { throw new CryptoAsymmetricException("FujisakiCipher:Decrypt", "The cipher is not initialized for decryption!", new ArgumentException()); } int c1Len = (m_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(m_N, c1); GF2Vector[] decC1 = CCA2Primitives.Decrypt((MPKCPrivateKey)m_asmKey, hrmVec); byte[] rBytes = decC1[0].GetEncoded(); // ... and obtain error vector z GF2Vector z = decC1[1]; byte[] mBytes; // get PRNG object.. using (KDF2 sr0 = new KDF2(GetDigest(m_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[m_dgtEngine.DigestSize]; m_dgtEngine.BlockUpdate(rmBytes, 0, rmBytes.Length); m_dgtEngine.DoFinal(hrm, 0); // compute Conv(H(r||m)) hrmVec = CCA2Conversions.Encode(m_N, m_T, hrm); // check that Conv(H(m||r)) = z if (!hrmVec.Equals(z)) { throw new CryptoAsymmetricException("FujisakiCipher:Decrypt", "Bad Padding: invalid ciphertext!", new InvalidDataException()); } // return plaintext m return(mBytes); }
public byte[] Decrypt(byte[] Input) { if (m_isEncryption) { throw new CryptoAsymmetricException("PointchevalCipher:Decrypt", "The cipher is not initialized for decryption!", new ArgumentException()); } int c1Len = (m_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(m_N, c1); GF2Vector[] c1Dec = CCA2Primitives.Decrypt((MPKCPrivateKey)m_asmKey, c1Vec); byte[] rPrimeBytes = c1Dec[0].GetEncoded(); // ... and obtain error vector z GF2Vector z = c1Dec[1]; byte[] mrBytes; // get PRNG object using (KDF2 sr0 = new KDF2(GetDigest(m_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) m_dgtEngine.BlockUpdate(mrBytes, 0, mrBytes.Length); byte[] hmr = new byte[m_dgtEngine.DigestSize]; m_dgtEngine.DoFinal(hmr, 0); // compute Conv(H(m||r)) c1Vec = CCA2Conversions.Encode(m_N, m_T, hmr); // check that Conv(H(m||r)) = z if (!c1Vec.Equals(z)) { throw new CryptoAsymmetricException("PointchevalCipher:Decrypt", "Bad Padding: Invalid ciphertext!", new ArgumentException()); } // split (m||r) to obtain m int kDiv8 = m_K >> 3; byte[][] mr = ByteUtils.Split(mrBytes, c2Len - kDiv8); // return plain text m return(mr[0]); }
/// <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); }