Example #1
0
 /// <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)));
 }
Example #2
0
        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);
 }
Example #4
0
 /// <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;
 }
Example #8
0
        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)
Example #14
0
 /// <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);
 }
Example #15
0
 /// <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];
Example #16
0
        /// <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));
        }
Example #17
0
 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);
 }
Example #19
0
 /// <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)