1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-11-29 12:45:20 +01:00
bitwarden-mobile/test/Core.Test/Services/CryptoFunctionServiceTests.cs
Matt Gibson 8d5614cd7b
Port send jslib to mobile (#1219)
* Expand Hkdf crypto functions

* Add tests for hkdf crypto functions

Took the testing infrastructure from bitwarden/server

* Move Hkdf to cryptoFunctionService

* Port changes from bitwarden/jslib#192

* Port changes from bitwarden/jslib#205

* Make Send Expiration Optional implement changes from bitwarden/jslib#242

* Bug fixes found by testing

* Test helpers

* Test conversion between model types

* Test SendService

These are mostly happy-path tests to ensure a reasonably correct
implementation

* Add run tests step to GitHub Actions

* Test send decryption

* Test Request generation from Send

* Constructor dependencies on separate lines

* Remove unused testing infrastructure

* Rename to match class name

* Move fat arrows to previous lines

* Handle exceptions in App layer

* PR review cleanups

* Throw when attempting to save an unkown Send Type

I think it's best to only throw on unknown send types here.
I don't think we want to throw whenever we encounter one since that would
do bad things like lock up Sync if clients get out of date relative to
servers. Instead, keep the client from ruining saved data by complaining
last minute that it doesn't know what it's doing.
2021-01-25 14:27:38 -06:00

88 lines
4.5 KiB
C#

using System;
using System.Threading.Tasks;
using Xunit;
using Bit.Core.Services;
using Bit.Core.Enums;
using Bit.Test.Common.AutoFixture.Attributes;
using System.Text;
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<ArgumentException>(
() => 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<ArgumentException>(
() => 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);
}
}
}