public override void Write(byte[] buffer, int offset, int count) { byte[] output = new byte[cipher.GetUpdateOutputSize(count)]; int encrypted = cipher.ProcessBytes(buffer, offset, count, output, 0); base.Write(output, 0, encrypted); }
public byte[] EncryptName(byte[] input, int paddedLength) { try { byte[] inputPadded = new byte[paddedLength]; if (input.Length > inputPadded.Length) { throw new ArgumentException($"Input is too long: {Encoding.UTF8.GetString(input)}"); } Array.Copy(input, 0, inputPadded, 0, input.Length); byte[] nonce = Util.GetSecretBytes(12); GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine()); cipher.Init(true, new AeadParameters(new KeyParameter(key), 128, nonce)); byte[] ciphertext = new byte[cipher.GetUpdateOutputSize(inputPadded.Length)]; cipher.ProcessBytes(inputPadded, 0, inputPadded.Length, ciphertext, 0); byte[] tag = new byte[cipher.GetOutputSize(0)]; cipher.DoFinal(tag, 0); return(ByteUtil.combine(nonce, ciphertext, tag)); } catch (InvalidCipherTextException ex) { throw new ArgumentException(null, ex); } }
internal static AesEncryptedResult Encrypt(byte[] key, byte[]?aad, byte[] requestData) { try { byte[] iv = Util.GetSecretBytes(12); var cipher = new GcmBlockCipher(new AesEngine()); cipher.Init(true, new AeadParameters(new KeyParameter(key), TAG_LENGTH_BITS, iv)); if (aad != null) { cipher.ProcessAadBytes(aad, 0, aad.Length); } byte[] cipherText1 = new byte[cipher.GetUpdateOutputSize(requestData.Length)]; cipher.ProcessBytes(requestData, 0, requestData.Length, cipherText1, 0); byte[] cipherText2 = new byte[cipher.GetOutputSize(0)]; cipher.DoFinal(cipherText2, 0); byte[] cipherText = ByteUtil.combine(cipherText1, cipherText2); byte[][] parts = ByteUtil.split(cipherText, cipherText.Length - TAG_LENGTH_BYTES, TAG_LENGTH_BYTES); return(new AesEncryptedResult(iv, parts[0], parts[1], aad)); } catch (Exception ex) { throw new InvalidOperationException(null, ex); } }
internal static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext, byte[] tag) { var cipher = new GcmBlockCipher(new AesEngine()); cipher.Init(false, new AeadParameters(new KeyParameter(key), TAG_LENGTH_BITS, iv)); byte[] combined = ByteUtil.combine(ciphertext, tag); byte[] cipherTextOne = new byte[cipher.GetUpdateOutputSize(combined.Length)]; cipher.ProcessBytes(combined, 0, combined.Length, cipherTextOne, 0); byte[] cipherTextTwo = new byte[cipher.GetOutputSize(0)]; cipher.DoFinal(cipherTextTwo, 0); return(ByteUtil.combine(cipherTextOne, cipherTextTwo)); }
private void OutputSizeTests() { byte[] K = new byte[16]; byte[] A = null; byte[] IV = new byte[16]; AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A); GcmBlockCipher cipher = InitCipher(null, true, parameters); if (cipher.GetUpdateOutputSize(0) != 0) { Fail("incorrect getUpdateOutputSize for initial 0 bytes encryption"); } if (cipher.GetOutputSize(0) != 16) { Fail("incorrect getOutputSize for initial 0 bytes encryption"); } cipher.Init(false, parameters); if (cipher.GetUpdateOutputSize(0) != 0) { Fail("incorrect getUpdateOutputSize for initial 0 bytes decryption"); } // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here if (cipher.GetOutputSize(0) != 0) { Fail("fragile getOutputSize for initial 0 bytes decryption"); } if (cipher.GetOutputSize(16) != 0) { Fail("incorrect getOutputSize for initial MAC-size bytes decryption"); } }
public static byte[] DeriveAccessKeyFrom(byte[] profileKey) { byte[] nonce = new byte[12]; byte[] input = new byte[16]; var cipher = new GcmBlockCipher(new AesEngine()); cipher.Init(false, new AeadParameters(new KeyParameter(profileKey), 128, nonce)); byte[] ciphertext = new byte[cipher.GetUpdateOutputSize(input.Length)]; cipher.ProcessBytes(input, 0, input.Length, ciphertext, 0); byte[] tag = new byte[cipher.GetOutputSize(0)]; cipher.DoFinal(tag, 0); byte[] combined = ByteUtil.combine(ciphertext, tag); return(ByteUtil.trim(combined, 16)); }
/// <summary> /// /// </summary> /// <param name="input"></param> /// <returns></returns> /// <exception cref="InvalidCiphertextException"></exception> public byte[] DecryptName(byte[] input) { try { if (input.Length < 12 + 16 + 1) { throw new InvalidCipherTextException($"Too short: {input.Length}"); } byte[] nonce = new byte[12]; Array.Copy(input, 0, nonce, 0, nonce.Length); GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine()); cipher.Init(false, new AeadParameters(new KeyParameter(key), 128, nonce)); byte[] paddedPlaintextOne = new byte[cipher.GetUpdateOutputSize(input.Length - 12)]; cipher.ProcessBytes(input, 12, input.Length - 12, paddedPlaintextOne, 0); byte[] paddedPlaintextTwo = new byte[cipher.GetOutputSize(0)]; cipher.DoFinal(paddedPlaintextTwo, 0); byte[] paddedPlaintext = ByteUtil.combine(paddedPlaintextOne, paddedPlaintextTwo); int plaintextLength = 0; for (int i = paddedPlaintext.Length - 1; i >= 0; i--) { if (paddedPlaintext[i] != 0x00) { plaintextLength = i + 1; break; } } byte[] plaintext = new byte[plaintextLength]; Array.Copy(paddedPlaintext, 0, plaintext, 0, plaintextLength); return(plaintext); } catch (InvalidCipherTextException ex) { throw new InvalidCiphertextException(ex); } }
private void RandomTest(SecureRandom srng, IGcmMultiplier m) { int kLength = 16 + 8 * srng.Next(3); byte[] K = new byte[kLength]; srng.NextBytes(K); int pLength = srng.Next(65536); byte[] P = new byte[pLength]; srng.NextBytes(P); int aLength = srng.Next(256); byte[] A = new byte[aLength]; srng.NextBytes(A); int saLength = srng.Next(256); byte[] SA = new byte[saLength]; srng.NextBytes(SA); int ivLength = 1 + srng.Next(256); byte[] IV = new byte[ivLength]; srng.NextBytes(IV); AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A); GcmBlockCipher cipher = InitCipher(m, true, parameters); byte[] C = new byte[cipher.GetOutputSize(P.Length)]; int predicted = cipher.GetUpdateOutputSize(P.Length); int split = srng.Next(SA.Length + 1); cipher.ProcessAadBytes(SA, 0, split); int len = cipher.ProcessBytes(P, 0, P.Length, C, 0); cipher.ProcessAadBytes(SA, split, SA.Length - split); if (predicted != len) { Fail("encryption reported incorrect update length in randomised test"); } len += cipher.DoFinal(C, len); if (C.Length != len) { Fail("encryption reported incorrect length in randomised test"); } byte[] encT = cipher.GetMac(); byte[] tail = new byte[C.Length - P.Length]; Array.Copy(C, P.Length, tail, 0, tail.Length); if (!AreEqual(encT, tail)) { Fail("stream contained wrong mac in randomised test"); } cipher.Init(false, parameters); byte[] decP = new byte[cipher.GetOutputSize(C.Length)]; predicted = cipher.GetUpdateOutputSize(C.Length); split = srng.Next(SA.Length + 1); cipher.ProcessAadBytes(SA, 0, split); len = cipher.ProcessBytes(C, 0, C.Length, decP, 0); cipher.ProcessAadBytes(SA, split, SA.Length - split); if (predicted != len) { Fail("decryption reported incorrect update length in randomised test"); } len += cipher.DoFinal(decP, len); if (!AreEqual(P, decP)) { Fail("incorrect decrypt in randomised test"); } byte[] decT = cipher.GetMac(); if (!AreEqual(encT, decT)) { Fail("decryption produced different mac from encryption"); } // // key reuse test // cipher.Init(false, AeadTestUtilities.ReuseKey(parameters)); decP = new byte[cipher.GetOutputSize(C.Length)]; split = NextInt(srng, SA.Length + 1); cipher.ProcessAadBytes(SA, 0, split); len = cipher.ProcessBytes(C, 0, C.Length, decP, 0); cipher.ProcessAadBytes(SA, split, SA.Length - split); len += cipher.DoFinal(decP, len); if (!AreEqual(P, decP)) { Fail("incorrect decrypt in randomised test"); } decT = cipher.GetMac(); if (!AreEqual(encT, decT)) { Fail("decryption produced different mac from encryption"); } }