internal void EncryptAndSign(byte[] inputNullable, int id, EncryptedFieldIds fieldId, out byte[] encrypted, out byte[] hmac) { if (inputNullable == null) { encrypted = null; hmac = null; return; } if (inputNullable.Length > 65535) { throw new ArgumentException(nameof(inputNullable)); } GetIVandKeys(id, fieldId, out var iv, out var aesKey, out var hmacKey); // encode length of input and add padding, to make it good for AES BinaryProcedures.CreateBinaryWriter(out var ms, out var w); w.Write((ushort)inputNullable.Length); w.Write(inputNullable); var bytesInLastBlock = (int)ms.Position % CryptoLibraries.AesBlockSize; if (bytesInLastBlock != 0) { var bytesRemainingTillFullAesBlock = CryptoLibraries.AesBlockSize - bytesInLastBlock; w.Write(_cryptoLibrary.GetRandomBytes(bytesRemainingTillFullAesBlock)); } var inputWithPadding = ms.ToArray(); encrypted = new byte[inputWithPadding.Length]; _cryptoLibrary.ProcessAesCbcBlocks(true, aesKey, iv, inputWithPadding, encrypted); hmac = _cryptoLibrary.GetSha256HMAC(hmacKey, encrypted); }
void GetIVandKeys(int id, EncryptedFieldIds fieldId, out byte[] iv, out byte[] aesKey, out byte[] hmacKey) { BinaryProcedures.CreateBinaryWriter(out var ms, out var w); w.Write(id); w.Write((byte)fieldId); var sha256result = _cryptoLibrary.GetHashSHA256(ms.ToArray()); var preKey = _keyProvider.HsmOperation(sha256result); _cryptoLibrary.DeriveKeysRFC5869_32bytes(preKey, sha256result, out aesKey, out hmacKey); iv = sha256result.Take(16).ToArray(); }
internal byte[] DecryptAndVerify(byte[] encryptedNullable, byte[] hmacNullable, int id, EncryptedFieldIds fieldId) { if (encryptedNullable == null || hmacNullable == null) { return(null); } GetIVandKeys(id, fieldId, out var iv, out var aesKey, out var hmacKey); var hmac = _cryptoLibrary.GetSha256HMAC(hmacKey, encryptedNullable); if (!MiscProcedures.EqualByteArrays(hmacNullable, hmac)) { throw new BadSignatureException(); } var decrypted = new byte[encryptedNullable.Length]; _cryptoLibrary.ProcessAesCbcBlocks(false, aesKey, iv, encryptedNullable, decrypted); using var reader = BinaryProcedures.CreateBinaryReader(decrypted, 0); var dataLength = reader.ReadUInt16(); return(reader.ReadBytes(dataLength)); }