コード例 #1
0
        internal override void WriteProperties(Utf8JsonWriter json)
        {
            if (KeyMaterial != default)
            {
                KeyMaterial.WriteProperties(json);
            }
            if (Enabled.HasValue || NotBefore.HasValue || Expires.HasValue)
            {
                json.WriteStartObject(AttributesPropertyNameBytes);

                if (Enabled.HasValue)
                {
                    json.WriteBoolean(EnabledPropertyNameBytes, Enabled.Value);
                }

                if (NotBefore.HasValue)
                {
                    json.WriteNumber(NotBeforePropertyNameBytes, NotBefore.Value.ToUnixTimeMilliseconds());
                }

                if (Expires.HasValue)
                {
                    json.WriteNumber(ExpiresPropertyNameBytes, Expires.Value.ToUnixTimeMilliseconds());
                }

                json.WriteEndObject();
            }
            if (Tags != null && Tags.Count > 0)
            {
                json.WriteStartObject(TagsPropertyNameBytes);

                foreach (var kvp in Tags)
                {
                    json.WriteString(kvp.Key, kvp.Value);
                }

                json.WriteEndObject();
            }
            if (Hsm.HasValue)
            {
                json.WriteBoolean(HsmPropertyNameBytes, Hsm.Value);
            }
        }
コード例 #2
0
        public async Task Store(KeyMaterial securityParamteres)
        {
            if (!KeysPath.Exists)
            {
                KeysPath.Create();
            }

            // Datetime it's just to be easy searchable.
            if (File.Exists(GetCurrentFile()))
            {
                File.Copy(GetCurrentFile(), Path.Combine(KeysPath.FullName, $"{_options.Value.KeyPrefix}old-{DateTime.Now:yyyy-MM-dd}-{securityParamteres.KeyId}.key"));
            }

            await File.WriteAllTextAsync(Path.Combine(KeysPath.FullName, $"{_options.Value.KeyPrefix}current-{securityParamteres.KeyId}.key"), JsonSerializer.Serialize(securityParamteres, new JsonSerializerOptions()
            {
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
            }));

            ClearCache();
        }
コード例 #3
0
    public async Task Should_Save_Probabilistic_Jwk_Recover_And_Signing(string algorithm)
    {
        var handler = new JsonWebTokenHandler();
        var now     = DateTime.Now;

        // Generate right now and in memory
        var newKey = new KeyMaterial(new CryptographicKey(algorithm));
        await _store.Store(newKey);

        // recovered from database
        var currentKey = await _store.GetCurrent();

        newKey.KeyId.Should().Be(currentKey.KeyId);
        var claims     = new ClaimsIdentity(GenerateClaim().Generate(5));
        var descriptor = new SecurityTokenDescriptor
        {
            Issuer             = "me",
            Audience           = "you",
            IssuedAt           = now,
            NotBefore          = now,
            Expires            = now.AddMinutes(5),
            Subject            = claims,
            SigningCredentials = new SigningCredentials(newKey, algorithm)
        };

        var descriptorFromDb = new SecurityTokenDescriptor
        {
            Issuer             = "me",
            Audience           = "you",
            IssuedAt           = now,
            NotBefore          = now,
            Expires            = now.AddMinutes(5),
            Subject            = claims,
            SigningCredentials = new SigningCredentials(currentKey, algorithm)
        };

        var jwt1 = handler.CreateToken(descriptor);
        var jwt2 = handler.CreateToken(descriptorFromDb);

        jwt1.Should().NotBe(jwt2);
    }
コード例 #4
0
        public override VerifyResult Verify(SignatureAlgorithm algorithm, byte[] digest, byte[] signature, CancellationToken cancellationToken)
        {
            // The JWK is not supported by this client. Send to the server.
            Argument.AssertNotNull(digest, nameof(digest));
            Argument.AssertNotNull(signature, nameof(signature));

            // The JWK is not supported by this client. Send to the server.
            if (KeyMaterial is null)
            {
                KeysEventSource.Singleton.AlgorithmNotSupported(nameof(Verify), _curve);
                return(null);
            }

            KeyCurveName algorithmCurve = algorithm.GetEcKeyCurveName();

            if (_curve.KeySize != algorithmCurve.KeySize)
            {
                throw new ArgumentException($"Signature algorithm {algorithm} key size {algorithmCurve.KeySize} does not match underlying key size {_curve.KeySize}");
            }

            if (_curve != algorithmCurve)
            {
                throw new ArgumentException($"Signature algorithm {algorithm} key curve name does not correspond to underlying key curve name {_curve}");
            }

            using ECDsa ecdsa = KeyMaterial.ToECDsa(false, false);
            if (ecdsa is null)
            {
                return(null);
            }

            bool isValid = ecdsa.VerifyHash(digest, signature);

            return(new VerifyResult
            {
                Algorithm = algorithm,
                IsValid = isValid,
                KeyId = KeyMaterial.Id,
            });
        }
コード例 #5
0
        public override SignResult Sign(SignatureAlgorithm algorithm, byte[] digest, CancellationToken cancellationToken)
        {
            Argument.AssertNotNull(digest, nameof(digest));

            ThrowIfTimeInvalid();

            // A private key is required to sign. Send to the server.
            if (MustRemote)
            {
                KeysEventSource.Singleton.PrivateKeyRequired(nameof(Sign));
                return(null);
            }

            HashAlgorithmName hashAlgorithm = algorithm.GetHashAlgorithmName();

            if (hashAlgorithm == default)
            {
                KeysEventSource.Singleton.AlgorithmNotSupported(nameof(Sign), algorithm);
                return(null);
            }

            RSASignaturePadding padding = algorithm.GetRsaSignaturePadding();

            if (padding is null)
            {
                KeysEventSource.Singleton.AlgorithmNotSupported(nameof(Sign), algorithm);
                return(null);
            }

            using RSA rsa = KeyMaterial.ToRSA(true);
            byte[] signature = rsa.SignHash(digest, hashAlgorithm, padding);

            return(new SignResult
            {
                Algorithm = algorithm,
                KeyId = KeyMaterial.Id,
                Signature = signature,
            });
        }
コード例 #6
0
        public override SignResult Sign(SignatureAlgorithm algorithm, byte[] digest, CancellationToken cancellationToken)
        {
            Argument.AssertNotNull(digest, nameof(digest));

            ThrowIfTimeInvalid();

            // A private key is required to sign. Send to the server.
            if (MustRemote)
            {
                // TODO: Log that we need a private key.
                return(null);
            }

            HashAlgorithmName hashAlgorithm = algorithm.GetHashAlgorithmName();

            if (hashAlgorithm == default)
            {
                // TODO: Log that we don't support the given algorithm.
                return(null);
            }

            RSASignaturePadding padding = algorithm.GetRsaSignaturePadding();

            if (padding is null)
            {
                // TODO: Log that we don't support the given algorithm.
                return(null);
            }

            using RSA rsa = KeyMaterial.ToRSA(true);
            byte[] signature = rsa.SignHash(digest, hashAlgorithm, padding);

            return(new SignResult
            {
                Algorithm = algorithm,
                KeyId = KeyMaterial.Id,
                Signature = signature,
            });
        }
コード例 #7
0
    public Task Store(KeyMaterial securityParamteres)
    {
        var possiblyEncryptedKeyElement = _dataProtector.Protect(JsonSerializer.Serialize(securityParamteres));

        // build the <key> element
        var keyElement = new XElement(Name,
                                      new XAttribute(IdAttributeName, securityParamteres.Id),
                                      new XAttribute(VersionAttributeName, 1),
                                      new XElement(CreationDateElementName, DateTimeOffset.UtcNow),
                                      new XElement(ActivationDateElementName, DateTimeOffset.UtcNow),
                                      new XElement(ExpirationDateElementName, DateTimeOffset.UtcNow.AddDays(_options.Value.DaysUntilExpire)),
                                      new XElement(DescriptorElementName,
                                                   new XAttribute(DeserializerTypeAttributeName, typeof(KeyMaterial).AssemblyQualifiedName !),
                                                   possiblyEncryptedKeyElement));

        // Persist it to the underlying repository and trigger the cancellation token.
        var friendlyName = string.Format(CultureInfo.InvariantCulture, "key-{0}", securityParamteres.KeyId);

        KeyRepository.StoreElement(keyElement, friendlyName);
        ClearCache();

        return(Task.CompletedTask);
    }
コード例 #8
0
    public async Task Should_Remove_Private_Key_From_Jwe_After_Update_A_Expired_Jwk(string algorithm, string encryption)
    {
        var alg = Algorithm.Create(algorithm).WithContentEncryption(encryption);

        var key        = new CryptographicKey(alg);
        var privateKey = new KeyMaterial(key);

        await _store.Store(privateKey);

        /*Remove private*/
        await _store.Revoke(privateKey);

        var keyDb      = (await _store.GetLastKeys(5)).First(w => w.KeyId == privateKey.KeyId);
        var jsonWebKey = keyDb.GetSecurityKey();

        jsonWebKey.Kty.Should().NotBeNullOrEmpty();
        jsonWebKey.HasPrivateKey.Should().BeFalse();
        switch (jsonWebKey.Kty)
        {
        case JsonWebAlgorithmsKeyTypes.EllipticCurve:
            jsonWebKey.D.Should().BeNullOrEmpty();
            break;

        case JsonWebAlgorithmsKeyTypes.RSA:
            jsonWebKey.D.Should().BeNullOrEmpty();
            jsonWebKey.DP.Should().BeNullOrEmpty();
            jsonWebKey.DQ.Should().BeNullOrEmpty();
            jsonWebKey.P.Should().BeNullOrEmpty();
            jsonWebKey.Q.Should().BeNullOrEmpty();
            jsonWebKey.QI.Should().BeNullOrEmpty();
            break;

        case JsonWebAlgorithmsKeyTypes.Octet:
            jsonWebKey.K.Should().NotBeNullOrEmpty();
            break;
        }
    }
コード例 #9
0
 private byte[] Decrypt(byte[] data, RSAEncryptionPadding padding)
 {
     using RSA rsa = KeyMaterial.ToRSA(true);
     return(rsa.Decrypt(data, padding));
 }
コード例 #10
0
 public async Task Should_Save_Crypto()
 {
     var key   = new CryptographicKey(DigitalSignaturesAlgorithm.RsaSsaPssSha256);
     var model = new KeyMaterial(key);
     await _store.Store(model);
 }
コード例 #11
0
 public static Key GetKey(this KeyMaterial keyMaterial, string passphrase)
 {
     return(new Key(VCL.DecryptWithPassphrase(passphrase, keyMaterial.EncryptedPrivateKey)));
 }