public AEADResult EncryptFinal(AEADResult previousResult) { var output = previousResult.RemainingOutput; if (_bufferOffset != 0) { output = EncryptBlock(output); } var tagCiphertextPaddingLength = (16 - (int)(_cSize / 8) % 16) % 16; _tagHash.Update(new byte[tagCiphertextPaddingLength]); _tagHash.Update(EndianBitConverter.Big.GetBytes(_aSize)); _tagHash.Update(EndianBitConverter.Big.GetBytes(_cSize)); var ctr = new CTRBlockCipher(_cipher); ctr.Init(new IVParameter(new NullCipherParameter(), _j0)); var blockResult = ctr.EncryptBlock(_tagHash.DigestBuffer(), output); output = blockResult.RemainingOutput; return(new AEADResult(previousResult.RemainingInput, output)); }
public AEADResult DecryptFinal(AEADResult previousResult) { // TODO SecurityAssert.AssertBuffer(input, inputOffset, _bufferOffset + TagLength); // TODO SecurityAssert.AssertBuffer(output, outputOffset, _bufferOffset); // Consume everything but the Tag previousResult = Decrypt(previousResult.RemainingInput, previousResult.RemainingOutput); var input = previousResult.RemainingInput; var output = previousResult.RemainingOutput; if (_bufferOffset != 0) { output = DecryptBlock(output); } var tagCiphertextPaddingLength = (16 - (int)(_cSize / 8) % 16) % 16; _tagHash.Update(new byte[tagCiphertextPaddingLength]); _tagHash.Update(EndianBitConverter.Big.GetBytes(_aSize)); _tagHash.Update(EndianBitConverter.Big.GetBytes(_cSize)); var tagCtr = new CTRBlockCipher(_cipher); tagCtr.Init(new IVParameter(new NullCipherParameter(), _j0)); var digest = _tagHash.DigestBuffer(); var calculatedTag = new byte[16]; tagCtr.EncryptBlock(digest, calculatedTag); var tag = input.Slice(0, _tagSize).ToArray(); SecurityAssert.AssertHash(calculatedTag, tag); return(new AEADResult(input.Slice(_tagSize), output)); }
public void Init(ICipherParameters parameters) { // setup AAD var aadParam = parameters as AADParameter; SecurityAssert.NotNull(aadParam); var a = aadParam !.AAD; var aSize = a.Length * 8; // setup IV var ivParam = aadParam !.Parameters as IVParameter; SecurityAssert.NotNull(ivParam); var iv = ivParam !.IV; var ivSize = iv.Length * 8; // setup cipher _cipher.Init(ivParam !.Parameters); // setup H subkey var h = new byte[16]; _cipher.EncryptBlock(new byte[16], 0, h, 0); // setup tag hash var tagHash = new GHash(h); tagHash.Update(a); var tagAADPaddingLength = 16 - a.Length % 16; tagHash.Update(new byte[tagAADPaddingLength]); // setup pre-counter block byte[] j0; if (iv.Length == 12) { // IV || 0^31 ||1 j0 = new byte[16]; Array.Copy(iv, j0, 12); j0[15] = 1; } else { // GHASH_H(IV || 0^(s+64) || [len(IV)]) var j0PaddingLength = 8 + (16 - iv.Length % 16) % 16; var j0Hash = new GHash(h); j0Hash.Update(iv); j0Hash.Update(new byte[j0PaddingLength]); j0Hash.Update(EndianBitConverter.Big.GetBytes((long)ivSize)); j0 = j0Hash.DigestBuffer(); } var ctr = new CTRBlockCipher(_cipher); ctr.Init(new IVParameter(j0)); ctr.Inc(); _state = new State(aSize, BlockLength, TagLength, j0, tagHash, ctr, _cipher); }