コード例 #1
0
        internal virtual CryptoKey GetLatestOrCreateIntermediateKey()
        {
            Option <EnvelopeKeyRecord> newestIntermediateKeyRecord = LoadLatestKeyRecord(partition.IntermediateKeyId);

            if (newestIntermediateKeyRecord.IsSome)
            {
                EnvelopeKeyRecord keyRecord = (EnvelopeKeyRecord)newestIntermediateKeyRecord;

                // If the key we just got back isn't expired, then just use it
                if (!IsKeyExpiredOrRevoked(keyRecord))
                {
                    try
                    {
                        return(WithExistingSystemKey(
                                   keyRecord.ParentKeyMeta.IfNone(() => throw new MetadataMissingException(
                                                                      "Could not find parentKeyMeta (SK) for intermediateKey ")),
                                   true,
                                   key => DecryptKey(keyRecord, key)));
                    }
                    catch (MetadataMissingException e)
                    {
                        Logger.LogDebug(
                            e,
                            "The SK for the IK ({keyId}, {created}) is missing or in an invalid state. Will create new IK instead.",
                            partition.IntermediateKeyId,
                            keyRecord.Created);
                    }
                }

                // If we're here we know we have an expired key.
                // If we're doing queued rotation, flag it and continue to use the expired key
                if (cryptoPolicy.IsQueuedKeyRotation())
                {
                    // TODO : Queued rotation
                    Logger.LogDebug("Queuing up IK {keyId} for rotation", partition.IntermediateKeyId);
                    try
                    {
                        return(WithExistingSystemKey(
                                   keyRecord.ParentKeyMeta.IfNone(() =>
                                                                  throw new MetadataMissingException(
                                                                      "Could not find parentKeyMeta (SK) for intermediateKey")),
                                   true,
                                   key => DecryptKey(keyRecord, key)));
                    }
                    catch (MetadataMissingException e)
                    {
                        Logger.LogDebug(
                            e,
                            "The SK for the IK ({keyId}, {created}) is missing or in an invalid state. Will create new IK instead.",
                            partition.IntermediateKeyId,
                            keyRecord.Created);
                    }
                }

                // If we're here then we're doing inline rotation and have an expired key.
                // Fall through as if we didn't have the key
            }

            DateTimeOffset intermediateKeyCreated = cryptoPolicy.TruncateToIntermediateKeyPrecision(DateTimeOffset.UtcNow);
            CryptoKey      intermediateKey        = crypto.GenerateKey(intermediateKeyCreated);

            try
            {
                EnvelopeKeyRecord newIntermediateKeyRecord = WithSystemKeyForWrite(systemCryptoKey =>
                                                                                   new EnvelopeKeyRecord(
                                                                                       intermediateKey.GetCreated(),
                                                                                       new KeyMeta(partition.SystemKeyId, systemCryptoKey.GetCreated()),
                                                                                       crypto.EncryptKey(intermediateKey, systemCryptoKey),
                                                                                       false));

                Logger.LogDebug(
                    "Attempting to store new IK {keyId}, for created {created}",
                    partition.IntermediateKeyId,
                    newIntermediateKeyRecord.Created);

                if (metastore.Store(
                        partition.IntermediateKeyId, newIntermediateKeyRecord.Created, newIntermediateKeyRecord.ToJson()))
                {
                    return(intermediateKey);
                }
                else
                {
                    Logger.LogDebug(
                        "Attempted to store new IK {keyId} but detected duplicate for created {created}, disposing newly created IK",
                        partition.IntermediateKeyId,
                        intermediateKey.GetCreated());
                    DisposeKey(intermediateKey, null);
                }
            }
            catch (Exception e)
            {
                DisposeKey(intermediateKey, e);
                throw new AppEncryptionException("Unable to store new Intermediate Key", e);
            }

            // If we're here, storing of the newly generated key failed above which means we attempted to
            // save a duplicate key to the metastore. If that's the case, then we know a valid key exists
            // in the metastore, so let's grab it and return it.

            // Using a new variable instead of the one above because the WithSystemKeyForWrite use above wants finality
            Option <EnvelopeKeyRecord> actualLatestIntermediateKeyRecord = LoadLatestKeyRecord(partition.IntermediateKeyId);

            if (actualLatestIntermediateKeyRecord.IsSome)
            {
                EnvelopeKeyRecord keyRecord = (EnvelopeKeyRecord)actualLatestIntermediateKeyRecord;

                // NOTE: Not wrapping this in try/catch to allow errors to bubble up. If we're missing meta in this flow, something's wrong.
                return(WithExistingSystemKey(
                           keyRecord.ParentKeyMeta.IfNone(() =>
                                                          throw new MetadataMissingException("Could not find parentKeyMeta (SK) for intermediateKey")),
                           true,
                           key => DecryptKey(keyRecord, key)));
            }
            else
            {
                throw new AppEncryptionException("IntermediateKey not present after LoadLatestKeyRecord retry");
            }
        }
コード例 #2
0
        internal static Mock <IMetastore <JObject> > CreateMetastoreMock(
            Partition partition,
            KeyManagementService kms,
            KeyState metaIK,
            KeyState metaSK,
            CryptoKeyHolder cryptoKeyHolder,
            IMetastore <JObject> metastore)
        {
            CryptoKey systemKey = cryptoKeyHolder.SystemKey;

            Mock <IMetastore <JObject> > metastoreSpy = new Mock <IMetastore <JObject> >();

            metastoreSpy
            .Setup(x => x.Load(It.IsAny <string>(), It.IsAny <DateTimeOffset>()))
            .Returns <string, DateTimeOffset>(metastore.Load);
            metastoreSpy
            .Setup(x => x.LoadLatest(It.IsAny <string>()))
            .Returns <string>(metastore.LoadLatest);
            metastoreSpy
            .Setup(x => x.Store(It.IsAny <string>(), It.IsAny <DateTimeOffset>(), It.IsAny <JObject>()))
            .Returns <string, DateTimeOffset, JObject>(metastore.Store);

            if (metaSK != KeyState.Empty)
            {
                if (metaSK == KeyState.Retired)
                {
                    // We create a revoked copy of the same key
                    DateTimeOffset created = systemKey.GetCreated();
                    systemKey = systemKey
                                .WithKey(bytes => Crypto.GenerateKeyFromBytes(bytes, created, true));
                }

                EnvelopeKeyRecord systemKeyRecord = new EnvelopeKeyRecord(
                    systemKey.GetCreated(), null, kms.EncryptKey(systemKey), systemKey.IsRevoked());
                metastore.Store(
                    partition.SystemKeyId,
                    systemKeyRecord.Created,
                    systemKeyRecord.ToJson());
            }

            if (metaIK != KeyState.Empty)
            {
                CryptoKey intermediateKey = cryptoKeyHolder.IntermediateKey;
                if (metaIK == KeyState.Retired)
                {
                    // We create a revoked copy of the same key
                    DateTimeOffset created = intermediateKey.GetCreated();
                    intermediateKey = intermediateKey
                                      .WithKey(bytes => Crypto.GenerateKeyFromBytes(bytes, created, true));
                }

                EnvelopeKeyRecord intermediateKeyRecord = new EnvelopeKeyRecord(
                    intermediateKey.GetCreated(),
                    new KeyMeta(partition.SystemKeyId, systemKey.GetCreated()),
                    Crypto.EncryptKey(intermediateKey, systemKey),
                    intermediateKey.IsRevoked());
                metastore.Store(
                    partition.IntermediateKeyId,
                    intermediateKeyRecord.Created,
                    intermediateKeyRecord.ToJson());
            }

            return(metastoreSpy);
        }