/// <summary> /// Derives a <see cref="UserKey"/> from the input user secret. /// </summary> /// <param name="userSecret">The secret used to derive the key.</param> /// <param name="keyDerivationSalt">The salt used to derive the key.</param> /// <param name="securitySettings">Security parameters for the <see cref="SecureArchive"/>.</param> public static UserKey DeriveFrom( RawUserSecret userSecret, ReadOnlySpan <byte> keyDerivationSalt, SecuritySettings securitySettings) { ArgCheck.NotNull(userSecret, nameof(userSecret)); ArgCheck.NotEmpty(keyDerivationSalt, nameof(keyDerivationSalt)); ArgCheck.IsValid(securitySettings, nameof(securitySettings)); var cryptoAlgoProperties = EncryptionAlgoProperties.For(securitySettings.EncryptionAlgo); // We'll use the user secret to derive the user key as well as the key ID. // The algorithm is: // let N be the number of bytes for the key // let M be the number of bytes for the keyId // keyMatter := Derive N + M bytes from the secret using the KDF // key := keyMatter[0..N-1] // keyId := base64url(keyMatter[N..]) var keyDerivationStrategy = CryptoHelpers.GetKeyDerivationStrategy(securitySettings.KeyDerivationFunction); var keyMatter = keyDerivationStrategy.DeriveKeyMatter( cryptoAlgoProperties.KeySizeInBytes + securitySettings.KeyIdSizeInBytes, userSecret.Key, keyDerivationSalt, securitySettings.KeyDerivationWorkFactor); var key = keyMatter.Slice(0, cryptoAlgoProperties.KeySizeInBytes); var keyId = Helpers.Base64UrlEncode(keyMatter.Slice(cryptoAlgoProperties.KeySizeInBytes)); return(new UserKey(keyId, key.ToArray())); }
/// <summary> /// Creates a new symmetric <see cref="ArchiveKey"/> that can be used with the /// algorithms described in the given <see cref="SecuritySettings"/>. /// </summary> /// <param name="securitySettings">The <see cref="SecuritySettings"/> for the archive.</param> /// <returns>The new <see cref="ArchiveKey"/>.</returns> public static ArchiveKey CreateNew(SecuritySettings securitySettings) { ArgCheck.IsValid(securitySettings, nameof(securitySettings)); var numKeyBytes = EncryptionAlgoProperties.For(securitySettings.EncryptionAlgo).KeySizeInBytes; return(new ArchiveKey(CryptoHelpers.GetRandomBytes(numKeyBytes))); }