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); } }
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(); }
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); }
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, }); }
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, }); }
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, }); }
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); }
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; } }
private byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) { using RSA rsa = KeyMaterial.ToRSA(true); return(rsa.Decrypt(data, padding)); }
public async Task Should_Save_Crypto() { var key = new CryptographicKey(DigitalSignaturesAlgorithm.RsaSsaPssSha256); var model = new KeyMaterial(key); await _store.Store(model); }
public static Key GetKey(this KeyMaterial keyMaterial, string passphrase) { return(new Key(VCL.DecryptWithPassphrase(passphrase, keyMaterial.EncryptedPrivateKey))); }