/// <summary> /// Gets whether this operation supports the other one (i.e. <see cref="KeyOperations.EncryptAndDecryt"/> /// supports <see cref="KeyOperations.EncryptOnly"/>). /// </summary> /// <param name="this">This operation.</param> /// <param name="o">The other operation.</param> /// <returns>Whether this operation supports the other one or not.</returns> public static bool Supports(this KeyOperations @this, KeyOperations o) { return(@this == o || (@this == KeyOperations.SignAndVerify && (o == KeyOperations.SignOnly || o == KeyOperations.VerifyOnly)) || (@this == KeyOperations.EncryptAndDecryt && (o == KeyOperations.DecryptOnly || o == KeyOperations.EncryptOnly)) || (@this == KeyOperations.WrapAndUnwrapKey && (o == KeyOperations.WrapKeyOnly || o == KeyOperations.UnwrapKeyOnly))); }
public static string AsString(KeyOperations keyType) { switch (keyType) { case KeyOperations.Encrypt: return("encrypt"); case KeyOperations.Decrypt: return("decrypt"); case KeyOperations.Sign: return("sign"); case KeyOperations.Verify: return("verify"); case KeyOperations.Wrap: return("wrapKey"); case KeyOperations.Unwrap: return("unwrapKey"); default: return(string.Empty); } }
ECKey(ISystemClock clock, string kid, KeyOperations ops, ECDsa ec, DateTime bestBefore, uint maxUseCount, bool isPrivateKey) : base(clock, kid, KeyType.Ec, ops, bestBefore, maxUseCount) { _ec = ec; _parameters = ec.ExportParameters(includePrivateParameters: isPrivateKey); KeySizeInBits = _ec.KeySize; JWKCurveName = GetJWKCurveName(_parameters.Curve.Oid); }
/// <summary> /// Initializes a new <see cref="KeyRequirement"/> for RSA or symmetric keys. /// </summary> /// <param name="keyType">Type of the key (<see cref="KeyType.Rsa"/> or <see cref="KeyType.Oct"/>).</param> /// <param name="operations">Supported key operations.</param> /// <param name="keySizeInBits">Size of the key.</param> /// <param name="initiatorAlgorithmName">See <see cref="InitiatorAlgorithmName"/>.</param> public KeyRequirement(KeyType keyType, KeyOperations operations, int keySizeInBits, string?initiatorAlgorithmName = null) { Throw.CheckArgument(keyType != KeyType.Ec); KeyType = keyType; Operations = operations; KeySizeInBits = keySizeInBits; InitiatorAlgorithmName = initiatorAlgorithmName; }
private protected KeyBase(ISystemClock clock, string kid, KeyType kty, KeyOperations ops, DateTime bestBefore, uint maxUseCount) { Clock = clock; Kty = kty; Kid = JsonEncodedText.Encode(kid); Operations = ops; CreationDate = Clock.UtcNow; BestBefore = bestBefore; MaxUseCount = maxUseCount; }
internal SymmetricKey(ISystemClock clock, string kid, KeyOperations ops, byte[] secretKey, DateTime bestBefore, uint maxUseCount) : base(clock, kid, KeyType.Oct, ops, bestBefore, maxUseCount) { if (!ops.IsBothSide() && ops != KeyOperations.DeriveBits && ops != KeyOperations.DeriveKey) { throw new ArgumentException($"Symmetric cannot support only '{ops}' operations.", nameof(ops)); } _key = secretKey; }
/// <summary> /// Initializes a new <see cref="KeyRequirement"/> for RSA or symmetric keys. /// </summary> /// <param name="keyType">Type of the key (<see cref="KeyType.Rsa"/> or <see cref="KeyType.Oct"/>).</param> /// <param name="operations">Supported key operations.</param> /// <param name="keySizeInBits">Size of the key.</param> /// <param name="initiatorAlgorithmName">See <see cref="InitiatorAlgorithmName"/>.</param> public KeyRequirement(KeyType keyType, KeyOperations operations, int keySizeInBits, string?initiatorAlgorithmName = null) { if (keyType == KeyType.Ec) { throw new ArgumentException("Sized requirement don't apply to EC keys.", nameof(keyType)); } KeyType = keyType; Operations = operations; KeySizeInBits = keySizeInBits; InitiatorAlgorithmName = initiatorAlgorithmName; }
static void Main(string[] args) { Console.WriteLine("Implementation of JSON Web Keys (RFC7517)"); JWK jwk = new JWK(); PublicKeyUse keyUse = PublicKeyUse.Signature; KeyOperations keyOperations = KeyOperations.ComputeDigitalSignature; Algorithm algorithm = Algorithm.ES256; string jwkString = jwk.JWKfromOptions(keyUse, keyOperations, algorithm); Console.WriteLine(jwkString); }
internal SymmetricKey(ISystemClock clock, string kid, KeyOperations ops, int keySizeInBits, DateTime bestBefore, uint maxUseCount) : base(clock, kid, KeyType.Oct, ops, bestBefore, maxUseCount) { int sz = keySizeInBits >> 3; if ((keySizeInBits & 3) != 0) { ++sz; } _key = new byte[sz]; RandomNumberGenerator.Fill(_key); }
public KeyBase?FindWithUseCount(KeyType keyType, KeyOperations operations, int keySize, DateTime bestBefore) { foreach (var k in this) { if (k.Kty == keyType && k.Operations.Supports(operations) && k.KeySizeInBits == keySize && k.UseCount < k.MaxUseCount && k.BestBefore < bestBefore) { return(k); } } return(null); }
private async Task <JsonWebKey> GetJsonWebKey(AllAlg alg, KeyOperations operation, Use use) { JsonWebKey result = null; var jsonWebKeys = await _jsonWebKeyRepository.GetByAlgorithmAsync( use, alg, new[] { operation }); if (jsonWebKeys != null && jsonWebKeys.Any()) { result = jsonWebKeys.First(); } return(result); }
/// <summary> /// This method must not be called directly: the static <see cref="Write(ICKBinaryWriter, KeyBase, KeyOperations?)"/> must be used. /// </summary> /// <param name="w">The target writer.</param> /// <param name="restrictedOperations">Optional replacement for <see cref="Operations"/>.</param> protected virtual void Write(ICKBinaryWriter w, KeyOperations?restrictedOperations) { KeyOperations o = Operations; if (restrictedOperations.HasValue) { if (!Operations.Supports(restrictedOperations.Value)) { throw new ArgumentException($"'{Operations}' must support '{restrictedOperations}'.", nameof(restrictedOperations)); } o = restrictedOperations.Value; } w.Write((byte)0); w.WriteEnum(Kty); w.Write(Kid.ToString()); w.WriteEnum(o); w.Write(CreationDate); w.Write(BestBefore); w.Write(MaxUseCount); w.Write(_oUseCount); }
public KeyBase?FindWithUseCount(KeyOperations operations, in Oid curveName, DateTime bestBefore)
/// <summary> /// Gets whether this operation supports both sides of the same algorithm: either <see cref="KeyOperations.EncryptAndDecryt"/>, /// <see cref="KeyOperations.WrapAndUnwrapKey"/> or <see cref="KeyOperations.SignAndVerify"/>. /// </summary> /// <param name="this">This operation.</param> /// <returns>Whether this operation supports both sides of the same algorithm.</returns> public static bool IsBothSide(this KeyOperations @this) { return(@this == KeyOperations.SignAndVerify || @this == KeyOperations.EncryptAndDecryt || @this == KeyOperations.WrapAndUnwrapKey); }
/// <summary> /// Gets the "key_ops" field value to use as a literal array. /// This is empty for <see cref="KeyOperations.None"/>. /// </summary> /// <param name="o">This operations.</param> /// <returns>The literal Json array of the operations.</returns> public static ReadOnlyMemory <byte> GetLiteralKeyOps(this KeyOperations o) => _keys[(int)o];
/// <summary> /// Called when a symmetric key has not been resolved in <see cref="TrustedParty.SymmetricKeys"/> or explicitly /// with a shared secret to establish a new symmetric key to prevent any man-in-the-middle attack. /// /// When called automatically, the fact that we don't have a symmetric key that satisfies the requirements /// doesn't mean that we don't have a symmetric key valid to sign the communication right now. /// However, if we don't (and there is no provided shared secret) then we use the "TrustedParty.InitialSecretPhrase" /// to derive a shared secret that must be the same as the one used by the other party. /// </summary> async ValueTask <KeyBase> CreateSymmetricKeyFromExchangeAsync(IActivityMonitor monitor, RemoteParty party, KeyOperations exchangedKeyOperations, int exchangedKeySizeInBits, DateTime exchangedKeyExpiration, uint maxUseCount, byte[]?sharedSecret) { // Each key size will have its own key: this is both safer and simpler even if this // triggers more exchanges. var exchangeAlgo = new DiffieHellmanAlgorithm(exchangedKeySizeInBits); Debug.Assert(exchangeAlgo.KeyRequirement != null); var now = Clock.UtcNow; // Our exchange key may be ephemeral (MaxUseCount = 1) or kept and reused (this depends on the configuration). var ourExchangeKey = LocalKeys.EnsureAsymmetricKey(monitor, party, exchangeAlgo.KeyRequirement, now, 0); Debug.Assert(ourExchangeKey != null, "We are asking for a 'EC' in order to 'DeriveKey' key, not a symmetric one."); Debug.Assert(ourExchangeKey.PublicKey != null, "This is a ECDiffieHellman key."); // We may also already have an available cached public key for the other party. var otherKeys = (ThirdPartyPublicKeyList)party.OtherKeys; JWKey?otherPublicKey = otherKeys.Find(exchangeAlgo.KeyRequirement, now); if (otherPublicKey == null || sharedSecret != null) { // We must exchange, either because there is an explicit sharedSecret or because we don't have a // a Diffie-Hellman key from the other party. // We must ensure a signer here or use the TrustedParty.InitialSecretPhrase. // The expiration is used in the initial secret and is checked: we have no more than 2 minutes to // receive the exchange. // Note that this DateTime is used by the other party to compute the shared secret and if the request // is signed, the verifier of the other party will use its ClockSkew: even if clocks are not perfectly // synchronized, this will work. DateTime exchangeRequestExpires = now.AddMinutes(2); Signer? signer = null; if (sharedSecret == null) { var signAlgo = party.OutgoingSignatureAlgorithm; Debug.Assert(signAlgo.KeyRequirement != null, "RemoteParty.OutgoingSignatureAlgorithm cannot be None."); var signKey = party.SymmetricKeys.FindOrCreateLocal(monitor, signAlgo.KeyRequirement, now, 0, false); if (signKey != null) { signer = new Signer(this, party, signAlgo, signKey, exchangeRequestExpires); } else { sharedSecret = party.CreateInitialSecret(monitor, exchangeRequestExpires); } } otherPublicKey = await GetExchangedPublicKeyAsync(monitor, otherKeys, exchangeRequestExpires, exchangedKeyOperations, exchangedKeyExpiration, exchangedKeySizeInBits, exchangeAlgo, ourExchangeKey, sharedSecret, signer); } return(LocalKeys.CreateSharedSecret(monitor, party.KeyRealm, exchangeAlgo, ourExchangeKey, otherPublicKey, exchangedKeyOperations, exchangedKeyExpiration, maxUseCount)); }
public AsymmetricKey(ISystemClock clock, string kid, KeyType kty, KeyOperations ops, DateTime bestBefore, uint maxUseCount) : base(clock, kid, kty, ops, bestBefore, maxUseCount) { }
RSAKey(ISystemClock clock, string name, KeyOperations ops, RSA rsa, DateTime bestBefore, uint maxUseCount, bool isPrivateKey) : base(clock, name, KeyType.Rsa, ops, bestBefore, maxUseCount) { _rsa = rsa; _parameters = rsa.ExportParameters(includePrivateParameters: isPrivateKey); }
/// <summary> /// Initializes a new <see cref="KeyRequirement"/> for elliptic curve keys. /// </summary> /// <param name="operations">Supported key operations.</param> /// <param name="curveName">The <see cref="Oid"/> of the named curve.</param> /// <param name="initiatorAlgorithmName">See <see cref="InitiatorAlgorithmName"/>.</param> public KeyRequirement(KeyOperations operations, in Oid curveName, string?initiatorAlgorithmName = null)