public async Task GetActiveSigningKeyPair_GivenRotationAndMasterKeyCert_ReturnsAKeyPairUsableForTokenSigning() { //Arrange var automocker = new AutoMocker(); var masterKey = new byte[256]; object cachedResult = null; automocker .SetupOptions(new AnonymousTokensConfig { KeyRotationEnabled = true, CurveName = "P-256", MasterKeyCertId = "master-key-cert", KeyRotationInterval = TimeSpan.FromDays(3), KeyRotationRollover = TimeSpan.FromDays(4) }); automocker .Setup <IMemoryCache, bool>(x => x.TryGetValue(It.IsAny <string>(), out cachedResult)) .Returns(false); automocker .Setup <IMemoryCache, ICacheEntry>(x => x.CreateEntry(It.IsAny <string>())) .Returns(Mock.Of <ICacheEntry>()); automocker .Setup <IAnonymousTokenMasterKeyLoader, Task <byte[]> >(x => x.LoadMasterKeyBytes()) .ReturnsAsync(masterKey); var target = automocker.CreateInstance <AnonymousTokenKeyStore>(); //Act var result = await target.GetActiveSigningKeyPair(); //Assert var ecParameters = CustomNamedCurves.GetByOid(X9ObjectIdentifiers.Prime256v1); var initiator = new Initiator(); var init = initiator.Initiate(ecParameters.Curve); var t = init.t; var r = init.r; var P = init.P; var tokenGenerator = new TokenGenerator(); var(Q, c, z) = tokenGenerator.GenerateToken(result.PrivateKey, result.PublicKey, ecParameters, P); var keyDto = result.AsValidationKey().AsKeyDto(); var clientSideEcParameters = CustomNamedCurves.GetByName(keyDto.Crv); // Matches keyDto.Crv == "P-256" var clientSidePublicKeyPoint = clientSideEcParameters.Curve.CreatePoint(new BigInteger(Convert.FromBase64String(keyDto.X)), new BigInteger(Convert.FromBase64String(keyDto.Y))); var W = initiator.RandomiseToken(clientSideEcParameters, clientSidePublicKeyPoint, P, Q, c, z, r); var tokenVerifier = new TokenVerifier(new InMemorySeedStore()); var isVerified = await tokenVerifier.VerifyTokenAsync(result.PrivateKey, ecParameters.Curve, t, W); isVerified.Should().BeTrue(); }
public async void VerifyToken_InvalidW_ThrowsException() { // Arrange var seedStoreMock = new Mock <ISeedStore>(); seedStoreMock.Setup(x => x.ExistsAsync(It.IsAny <byte[]>())).Returns(Task.FromResult(false)); seedStoreMock.Setup(x => x.SaveAsync(It.IsAny <byte[]>())).Returns(Task.FromResult(true)); var tokenVerifier = new TokenVerifier(seedStoreMock.Object); var privateKey = new BigInteger(Hex.Decode("01301abfe491c0aff380269c966254ac43fdd97469234c7739ada975368181fe")); byte[] t = Hex.Decode("4391837b1e50cb0b075fc91ea9a85a4a795195557f4fb9a971e10b94370dee2b"); var W = _ecParameters.Curve.DecodePoint(Hex.Decode("04ce1e55cff15c5f5fbd0abca2a2849cf04ccda1c601a849ab28eb6161a0c32e96b6346728d8d3464754361977ee1a1c68120cb0575506cafe6e24d595de92069d")); // Create a new point with invalid coordinates var invalidW = _ecParameters.Curve.CreatePoint(W.XCoord.ToBigInteger().Add(BigInteger.One), W.YCoord.ToBigInteger()); try { // Act await tokenVerifier.VerifyTokenAsync(privateKey, _ecParameters.Curve, t, invalidW); } catch (AnonymousTokensException) { Assert.True(true, "an invalid point should raise an exception"); } }
public async void Run() { // 1. Initiate communication with a masked point P = r*T = r*Hash(t) var init = _initiator.Initiate(_ecParameters.Curve); var t = init.t; var r = init.r; var P = init.P; // 2. Generate token Q = k*P and proof (c,z) of correctness var(Q, proofC, proofZ) = _tokenGenerator.GenerateToken(_privateKey, _publicKey.Q, _ecParameters, P); // 3. Randomise the token Q, by removing the mask r: W = (1/r)*Q = k*T. Also checks that proof (c,z) is correct. var W = _initiator.RandomiseToken(_ecParameters, _publicKey.Q, P, Q, proofC, proofZ, r); // 4. Verify that the token (t,W) is correct. var isVerified = await _tokenVerifier.VerifyTokenAsync(_privateKey, _ecParameters.Curve, t, W); if (isVerified == false) { Assert.True(false, "token was expected to be valid"); } }
public async void VerifyToken_tExistsInSeedStore_ReturnsFalse() { // Arrange var seedStoreMock = new Mock <ISeedStore>(); seedStoreMock.Setup(x => x.ExistsAsync(It.IsAny <byte[]>())).Returns(Task.FromResult(true)); var privateKey = new BigInteger(Hex.Decode("01301abfe491c0aff380269c966254ac43fdd97469234c7739ada975368181fe")); byte[] t = Hex.Decode("4391837b1e50cb0b075fc91ea9a85a4a795195557f4fb9a971e10b94370dee2b"); var W = _ecParameters.Curve.DecodePoint(Hex.Decode("04ce1e55cff15c5f5fbd0abca2a2849cf04ccda1c601a849ab28eb6161a0c32e96b6346728d8d3464754361977ee1a1c68120cb0575506cafe6e24d595de92069d")); var tokenVerifier = new TokenVerifier(seedStoreMock.Object); // Act var actual = await tokenVerifier.VerifyTokenAsync(privateKey, _ecParameters.Curve, t, W); // Assert Assert.False(actual); }
public async Task Handle_GivenRequestForNewToken_ReturnsAnonymousTokenResponse() { //Arrange var automocker = new AutoMocker(); var curveName = "P-256"; var ecParameters = CustomNamedCurves.GetByName(curveName); var initiator = new Initiator(); var init = initiator.Initiate(ecParameters.Curve); var t = init.t; var r = init.r; var P = init.P; var privateKey = await new InMemoryPrivateKeyStore().GetAsync(); var publicKey = (await new InMemoryPublicKeyStore().GetAsync()).Q; var signingKeyPair = new AnonymousTokenSigningKeypair("some-kid-123", curveName, privateKey, publicKey); var tokenGenerator = new TokenGenerator(); var(expectedSignedPoint, expectedProofChallenge, expectedProofResponse) = tokenGenerator.GenerateToken(privateKey, publicKey, ecParameters, P); var tokenVerifier = new TokenVerifier(new InMemorySeedStore()); var tokenRequest = new IssueAnonymousToken.Command { JwtTokenId = "token-a", JwtTokenExpiry = DateTime.Now.AddMinutes(10), RequestData = new AnonymousTokenRequest { MaskedPoint = Convert.ToBase64String(P.GetEncoded()) } }; automocker .SetupOptions(new AnonymousTokensConfig { Enabled = true }); automocker .Setup <IAnonymousTokenIssueRecordRepository, Task <IEnumerable <AnonymousTokenIssueRecord> > >(x => x.RetrieveRecordsJwtToken(It.IsAny <string>())) .Returns <string>(x => Task.FromResult(Enumerable.Empty <AnonymousTokenIssueRecord>())); automocker .Setup <IAnonymousTokensKeyStore, Task <AnonymousTokenSigningKeypair> >(x => x.GetActiveSigningKeyPair()) .ReturnsAsync(signingKeyPair); automocker .Setup <ITokenGenerator, (ECPoint, BigInteger, BigInteger)>(x => x.GenerateToken(privateKey, publicKey, ecParameters, It.Is <ECPoint>(y => y.Equals(P)))) .Returns((expectedSignedPoint, expectedProofChallenge, expectedProofResponse)); var target = automocker.CreateInstance <IssueAnonymousToken.Handler>(); //Act var result = await target.Handle(tokenRequest, new CancellationToken()); //Assert using (new AssertionScope()) { result.HasValue.Should().BeTrue(); var anonymousTokenResponse = result.ValueOrFailure(); anonymousTokenResponse.Kid.Should().Be("some-kid-123"); var Q = ecParameters.Curve.DecodePoint(Convert.FromBase64String(anonymousTokenResponse.SignedPoint)); var c = new BigInteger(Convert.FromBase64String(anonymousTokenResponse.ProofChallenge)); var z = new BigInteger(Convert.FromBase64String(anonymousTokenResponse.ProofResponse)); Q.Should().Be(expectedSignedPoint); c.Should().Be(expectedProofChallenge); z.Should().Be(expectedProofResponse); var W = initiator.RandomiseToken(ecParameters, publicKey, P, Q, c, z, r); var isVerified = await tokenVerifier.VerifyTokenAsync(privateKey, ecParameters.Curve, t, W); isVerified.Should().BeTrue(); } }