diff --git a/src/Core/Tokens/DataProtectorTokenFactory.cs b/src/Core/Tokens/DataProtectorTokenFactory.cs index 17f7873ae7..8029b35547 100644 --- a/src/Core/Tokens/DataProtectorTokenFactory.cs +++ b/src/Core/Tokens/DataProtectorTokenFactory.cs @@ -16,6 +16,13 @@ namespace Bit.Core.Tokens public string Protect(T data) => data.ToToken().ProtectWith(_dataProtector).WithPrefix(_clearTextPrefix).ToString(); + /// + /// Unprotect token + /// + /// The token to parse + /// The tokenable type to parse to + /// The parsed tokenable + /// Throws CryptographicException if fails to unprotect public T Unprotect(string token) => Tokenable.FromToken(new Token(token).RemovePrefix(_clearTextPrefix).UnprotectWith(_dataProtector).ToString()); diff --git a/src/Core/Tokens/ISymmetricKeyProtectedTokenFactory.cs b/src/Core/Tokens/ISymmetricKeyProtectedTokenFactory.cs deleted file mode 100644 index 0766113d9e..0000000000 --- a/src/Core/Tokens/ISymmetricKeyProtectedTokenFactory.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Bit.Core.Tokens -{ - public interface ISymmetricKeyProtectedTokenFactory where T : Tokenable - { - string Protect(string key, T data); - T Unprotect(string key, string token); - bool TryUnprotect(string key, string token, out T data); - bool TokenValid(string key, string token); - } -} diff --git a/test/Core.Test/Tokens/DataProtectorTokenFactoryTests.cs b/test/Core.Test/Tokens/DataProtectorTokenFactoryTests.cs index 35fcd33a58..8a75a07900 100644 --- a/test/Core.Test/Tokens/DataProtectorTokenFactoryTests.cs +++ b/test/Core.Test/Tokens/DataProtectorTokenFactoryTests.cs @@ -1,4 +1,5 @@ -using AutoFixture; +using System.Security.Cryptography; +using AutoFixture; using Bit.Core.Tokens; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; @@ -50,5 +51,78 @@ namespace Bit.Core.Test.Tokens Assert.NotEqual(new Token(token).RemovePrefix(prefix), tokenable.ToToken()); } + + [Theory, BitAutoData] + public void ThrowsIfUnprotectFails(TestTokenable tokenable) + { + var sutProvider = GetSutProvider(); + + var token = sutProvider.Sut.Protect(tokenable); + token += "stuff to make sure decryption fails"; + + Assert.Throws(() => sutProvider.Sut.Unprotect(token)); + } + + [Theory, BitAutoData] + public void TryUnprotect_FalseIfUnprotectFails(TestTokenable tokenable) + { + var sutProvider = GetSutProvider(); + var token = sutProvider.Sut.Protect(tokenable) + "fail decryption"; + + var result = sutProvider.Sut.TryUnprotect(token, out var data); + + Assert.False(result); + Assert.Null(data); + } + + [Theory, BitAutoData] + public void TokenValid_FalseIfUnprotectFails(TestTokenable tokenable) + { + var sutProvider = GetSutProvider(); + var token = sutProvider.Sut.Protect(tokenable) + "fail decryption"; + + var result = sutProvider.Sut.TokenValid(token); + + Assert.False(result); + } + + + [Theory, BitAutoData] + public void TokenValid_FalseIfTokenInvalid(TestTokenable tokenable) + { + var sutProvider = GetSutProvider(); + + tokenable.ForceInvalid = true; + var token = sutProvider.Sut.Protect(tokenable); + + var result = sutProvider.Sut.TokenValid(token); + + Assert.False(result); + } + + [Theory, BitAutoData] + public void TryUnprotect_TrueIfSuccess(TestTokenable tokenable) + { + var sutProvider = GetSutProvider(); + var token = sutProvider.Sut.Protect(tokenable); + + var result = sutProvider.Sut.TryUnprotect(token, out var data); + + Assert.True(result); + AssertHelper.AssertPropertyEqual(tokenable, data); + } + + [Theory, BitAutoData] + public void TokenValid_TrueIfSuccess(TestTokenable tokenable) + { + tokenable.ForceInvalid = false; + var sutProvider = GetSutProvider(); + var token = sutProvider.Sut.Protect(tokenable); + + var result = sutProvider.Sut.TokenValid(token); + + Assert.True(result); + } + } } diff --git a/test/Core.Test/Tokens/TestTokenable.cs b/test/Core.Test/Tokens/TestTokenable.cs index 0f2e2536c9..7e73cd5e9d 100644 --- a/test/Core.Test/Tokens/TestTokenable.cs +++ b/test/Core.Test/Tokens/TestTokenable.cs @@ -1,10 +1,14 @@ -using Bit.Core.Tokens; +using System.Text.Json.Serialization; +using Bit.Core.Tokens; namespace Bit.Core.Test.Tokens { public class TestTokenable : Tokenable { - public override bool Valid => true; + public bool ForceInvalid { get; set; } = false; + + [JsonIgnore] + public override bool Valid => !ForceInvalid; } public class TestExpiringTokenable : ExpiringTokenable