using System; using System.Text; using System.Threading.Tasks; using Bit.Core.Enums; using Bit.Core.Services; using Bit.Test.Common.AutoFixture.Attributes; using Xunit; namespace Bit.Core.Test.Services { public class CryptoFunctionServiceTests { const string regular256Key = "qBUmEYtwTwwGPuw/z6bs/qYXXYNUlocFlyAuuANI8Pw="; const string utf8256Key = "6DfJwW1R3txgiZKkIFTvVAb7qVlG7lKcmJGJoxR2GBU="; const string unicode256Key = "gejGI82xthA+nKtKmIh82kjw+ttHr+ODsUoGdu5sf0A="; const string regular512Key = "xe5cIG6ZfwGmb1FvsOedM0XKOm21myZkjL/eDeKIqqM="; const string utf8512Key = "XQMVBnxVEhlvjSFDQc77j5GDE9aorvbS0vKnjhRg0LY="; const string unicode512Key = "148GImrTbrjaGAe/iWEpclINM8Ehhko+9lB14+52lqc="; const string regularSalt = "salt"; const string utf8Salt = "üser_salt"; const string unicodeSalt = "😀salt🙏"; const string regularInfo = "info"; const string utf8Info = "üser_info"; const string unicodeInfo = "😀info🙏"; const string prk16Byte = "criAmKtfzxanbgea5/kelQ=="; const string prk32Byte = "F5h4KdYQnIVH4rKH0P9CZb1GrR4n16/sJrS0PsQEn0Y="; const string prk64Byte = "ssBK0mRG17VHdtsgt8yo4v25CRNpauH+0r2fwY/E9rLyaFBAOMbIeTry+" + "gUJ28p8y+hFh3EI9pcrEWaNvFYonQ=="; [Theory, AutoSubstitutionData] async public Task HkdfExpand_PrkTooSmall_Throws(PclCryptoFunctionService sut) { var exception = await Assert.ThrowsAsync( () => sut.HkdfExpandAsync(Convert.FromBase64String(prk16Byte), "info", 32, HkdfAlgorithm.Sha256)); Assert.Contains("too small", exception.Message); } [Theory, AutoSubstitutionData] async public Task HkdfoExpand_OutputTooBig_Throws(PclCryptoFunctionService sut) { var exception = await Assert.ThrowsAsync( () => sut.HkdfExpandAsync(Convert.FromBase64String(prk32Byte), "info", 8161, HkdfAlgorithm.Sha256)); Assert.Contains("too large", exception.Message); } [Theory] [InlineAutoSubstitutionData(regular256Key, HkdfAlgorithm.Sha256, prk16Byte, regularSalt, regularInfo)] [InlineAutoSubstitutionData(utf8256Key, HkdfAlgorithm.Sha256, prk16Byte, utf8Salt, utf8Info)] [InlineAutoSubstitutionData(unicode256Key, HkdfAlgorithm.Sha256, prk16Byte, unicodeSalt, unicodeInfo)] [InlineAutoSubstitutionData(regular512Key, HkdfAlgorithm.Sha512, prk16Byte, regularSalt, regularInfo)] [InlineAutoSubstitutionData(utf8512Key, HkdfAlgorithm.Sha512, prk16Byte, utf8Salt, utf8Info)] [InlineAutoSubstitutionData(unicode512Key, HkdfAlgorithm.Sha512, prk16Byte, unicodeSalt, unicodeInfo)] async public Task Hkdf_Success(string expectedKey, HkdfAlgorithm algorithm, string ikmString, string salt, string info, PclCryptoFunctionService sut) { byte[] ikm = Convert.FromBase64String(ikmString); var key = await sut.HkdfAsync(ikm, salt, info, 32, algorithm); Assert.Equal(expectedKey, Convert.ToBase64String(key)); var keyFromByteArray = await sut.HkdfAsync(ikm, Encoding.UTF8.GetBytes(salt), Encoding.UTF8.GetBytes(info), 32, algorithm); Assert.Equal(key, keyFromByteArray); } [Theory] [InlineAutoSubstitutionData("BnIqJlfnHm0e/2iB/15cbHyR19ARPIcWRp4oNS22CD8=", HkdfAlgorithm.Sha256, prk32Byte, 32, regularInfo)] [InlineAutoSubstitutionData("BnIqJlfnHm0e/2iB/15cbHyR19ARPIcWRp4oNS22CD9BV+/queOZenPNkDhmlVyL2WZ3OSU5+7ISNF5NhNfvZA==", HkdfAlgorithm.Sha256, prk32Byte, 64, regularInfo)] [InlineAutoSubstitutionData("uLWbMWodSBms5uGJ5WTRTesyW+MD7nlpCZvagvIRXlk=", HkdfAlgorithm.Sha512, prk64Byte, 32, regularInfo)] [InlineAutoSubstitutionData("uLWbMWodSBms5uGJ5WTRTesyW+MD7nlpCZvagvIRXlkY5Pv0sB+MqvaopmkC6sD/j89zDwTV9Ib2fpucUydO8w==", HkdfAlgorithm.Sha512, prk64Byte, 64, regularInfo)] async public Task HkdfExpand_Success(string expectedKey, HkdfAlgorithm algorithm, string prkString, int outputByteSize, string info, PclCryptoFunctionService sut) { var prk = Convert.FromBase64String(prkString); var key = await sut.HkdfExpandAsync(prk, info, outputByteSize, algorithm); Assert.Equal(expectedKey, Convert.ToBase64String(key)); var keyFromByteArray = await sut.HkdfExpandAsync(prk, Encoding.UTF8.GetBytes(info), outputByteSize, algorithm); Assert.Equal(key, keyFromByteArray); } } }