Skip to content

Commit

Permalink
refactor!: refactor KeyName and KeyValue
Browse files Browse the repository at this point in the history
  • Loading branch information
carlh98 committed Nov 24, 2023
1 parent 31acf7e commit 8ca88df
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 100 deletions.
3 changes: 2 additions & 1 deletion BREAKING_CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
## 2.0.0

* Added support .net 7
* Dropped support for .net 6
* Dropped support for .net 6
* Refactor KeyName to Key and KeyValue to Value
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ await biometryService.ScanBiometry(CancellationToken.None);
This method encrypts a value and stores it into the platform secure storage with the given key name.

``` cs
await biometryService.Encrypt(CancellationToken.None, "KeyName", "KeyValue");
await biometryService.Encrypt(CancellationToken.None, "Key", "Value");
```

On Android, a new `CryptoObject` from `AndroidX.Biometric` is created with a key as a parameter. Then the data is encrypted and presented to the `BiometricPrompt` manager.
Expand All @@ -182,7 +182,7 @@ On iOS, the `SecKeyChain` is used to store a string linked to a key. The OS is i
This method decrypts and gets the data associated to the given key.

``` cs
await biometryService.Decrypt(CancellationToken.None, "KeyName");
await biometryService.Decrypt(CancellationToken.None, "Key");
```

On Android, the method retrieves the shared preference encrypted data, then decrypts it with the secret as a parameter by presenting it to the `BiometricPrompt` manager.
Expand All @@ -194,7 +194,7 @@ On iOS, the method retrieves the encrypted data from the `SecKeyChain` with the
This method removes the ecrypted value from the platform secure storage.

``` cs
biometryService.Remove("KeyName");
biometryService.Remove("Key");
```

On Android, the method removes the encrypted data from the shared preferences.
Expand Down
18 changes: 9 additions & 9 deletions src/BiometryService.Abstractions/IBiometryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,32 @@ public interface IBiometryService
Task ScanBiometry(CancellationToken ct);

/// <summary>
/// Encrypts the value and stores it into the platform secure storage with the given <paramref name="keyName"/>.
/// Encrypts the value and stores it into the platform secure storage with the given <paramref name="key"/>.
/// </summary>
/// <remarks>
/// Catch and throw <see cref="BiometryException"/> for general biometry errors.
/// </remarks>
/// <param name="ct"><see cref="CancellationToken" />.</param>
/// <param name="keyName">The name of the key.</param>
/// <param name="keyValue">The value to be encrypt.</param>
Task Encrypt(CancellationToken ct, string keyName, string keyValue);
/// <param name="key">The name of the key.</param>
/// <param name="value">The value to be encrypt.</param>
Task Encrypt(CancellationToken ct, string key, string value);

/// <summary>
/// Decrypts and gets the data associated to the given <paramref name="keyName"/>.
/// Decrypts and gets the data associated to the given <paramref name="key"/>.
/// </summary>
/// <remarks>
/// Catch and throw <see cref="BiometryException"/> for general biometry errors.
/// Catch and throw <see cref="OperationCanceledException"/> if the user cancelled the operation.
/// </remarks>
/// <param name="ct"><see cref="CancellationToken" />.</param>
/// <param name="keyName">The name of the Key.</param>
/// <param name="key">The name of the Key.</param>
/// <returns>The decrypted data associated to the key.</returns>
Task<string> Decrypt(CancellationToken ct, string keyName);
Task<string> Decrypt(CancellationToken ct, string key);

/// <summary>
/// Removes the ecrypted value in the platform secure storage.
/// </summary>
/// <param name="keyName">The name of the Key.</param>
/// <param name="key">The name of the Key.</param>
/// <exception cref="BiometryException">Thrown for general biometry errors.</exception>
void Remove(string keyName);
void Remove(string key);
}
6 changes: 3 additions & 3 deletions src/BiometryService/BaseBiometryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ public BaseBiometryService(ILoggerFactory loggerFactory = null)
}

/// <inheritdoc/>
public abstract Task<string> Decrypt(CancellationToken ct, string keyName);
public abstract Task<string> Decrypt(CancellationToken ct, string key);

/// <inheritdoc/>
public abstract Task Encrypt(CancellationToken ct, string keyName, string keyValue);
public abstract Task Encrypt(CancellationToken ct, string key, string value);

/// <inheritdoc/>
public abstract Task<BiometryCapabilities> GetCapabilities(CancellationToken ct);

/// <inheritdoc/>
public abstract void Remove(string keyName);
public abstract void Remove(string key);

/// <inheritdoc/>
public abstract Task ScanBiometry(CancellationToken ct);
Expand Down
60 changes: 30 additions & 30 deletions src/BiometryService/BiometryService.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,16 @@ public override async Task ScanBiometry(CancellationToken ct)
}

/// <inheritdoc/>
public override async Task Encrypt(CancellationToken ct, string keyName, string value)
public override async Task Encrypt(CancellationToken ct, string key, string value)
{
if (Logger.IsEnabled(LogLevel.Debug))
{
Logger.LogDebug($"Encrypting the fingerprint for the key '{keyName}'.");
Logger.LogDebug($"Encrypting the fingerprint for the key '{key}'.");
}

await ValidateBiometryCapabilities(ct);

var crypto = CreateCryptoObject(keyName);
var crypto = CreateCryptoObject(key);
var result = await AuthenticateBiometry(ct, crypto);
var valueToEncrypt = Encoding.UTF8.GetBytes(value);
var encryptedData = result.CryptoObject.Cipher.DoFinal(valueToEncrypt);
Expand All @@ -108,26 +108,26 @@ public override async Task Encrypt(CancellationToken ct, string keyName, string

if (Logger.IsEnabled(LogLevel.Information))
{
Logger.LogInformation($"Succcessfully encrypted the fingerprint for the key'{keyName}'.");
Logger.LogInformation($"Succcessfully encrypted the fingerprint for the key'{key}'.");
}

var encodedData = Base64.EncodeToString(bytes, Base64Flags.NoWrap);
var sharedpref = _applicationContext.GetSharedPreferences(PREFERENCE_NAME, FileCreationMode.Private);
sharedpref.Edit().PutString(keyName, encodedData).Apply();
sharedpref.Edit().PutString(key, encodedData).Apply();
}

/// <inheritdoc/>
public override async Task<string> Decrypt(CancellationToken ct, string keyName)
public override async Task<string> Decrypt(CancellationToken ct, string key)
{
if (Logger.IsEnabled(LogLevel.Debug))
{
Logger.LogDebug($"Decrypting the fingerprint for the key '{keyName}'.");
Logger.LogDebug($"Decrypting the fingerprint for the key '{key}'.");
}

await ValidateBiometryCapabilities(ct);

var sharedpref = _applicationContext.GetSharedPreferences(PREFERENCE_NAME, FileCreationMode.Private);
var storedData = sharedpref.GetString(keyName, null);
var storedData = sharedpref.GetString(key, null);

if (storedData == null)
{
Expand All @@ -154,38 +154,38 @@ public override async Task<string> Decrypt(CancellationToken ct, string keyName)
data.Length - 16
);

var crypto = GetCryptoObject(keyName, iv);
var crypto = GetCryptoObject(key, iv);
var result = await AuthenticateBiometry(ct, crypto);
var decryptedData = result.CryptoObject.Cipher.DoFinal(buffer);

if (Logger.IsEnabled(LogLevel.Information))
{
Logger.LogInformation($"Succcessfully decrypted the fingerprint for the key '{keyName}'.");
Logger.LogInformation($"Succcessfully decrypted the fingerprint for the key '{key}'.");
}

return Encoding.ASCII.GetString(decryptedData);
}

/// <inheritdoc/>
public override void Remove(string keyName)
public override void Remove(string key)
{
try
{
var sharedpref = _applicationContext.GetSharedPreferences(PREFERENCE_NAME, FileCreationMode.Private);
sharedpref.Edit().Remove(keyName).Apply();
sharedpref.Edit().Remove(key).Apply();

if (Logger.IsEnabled(LogLevel.Debug))
{
Logger.LogDebug("The key '{keyName}' has been successfully removed.", keyName);
Logger.LogDebug("The key '{key}' has been successfully removed.", key);
}
}
catch (System.Exception)
{
if (Logger.IsEnabled(LogLevel.Debug))
{
Logger.LogDebug("The key '{keyName}' has not been successfully removed.", keyName);
Logger.LogDebug("The key '{key}' has not been successfully removed.", key);
}
throw new BiometryException(BiometryExceptionReason.Failed, $"Something went wrong while removing the key '{keyName}'.");
throw new BiometryException(BiometryExceptionReason.Failed, $"Something went wrong while removing the key '{key}'.");
}
}

Expand Down Expand Up @@ -296,23 +296,23 @@ public override void Remove(string keyName)
}
}

private BiometricPrompt.CryptoObject CreateCryptoObject(string keyName)
private BiometricPrompt.CryptoObject CreateCryptoObject(string key)
{
var cipher = Cipher.GetInstance(CIPHER_NAME);

if (_keyStore.IsKeyEntry(keyName))
if (_keyStore.IsKeyEntry(key))
{
_keyStore.DeleteEntry(keyName);
_keyStore.DeleteEntry(key);
}

if (Logger.IsEnabled(LogLevel.Debug))
{
Logger.LogDebug($"Generating a symmetric pair (key name: '{keyName}').");
Logger.LogDebug($"Generating a symmetric pair (key name: '{key}').");
}

var keygen = KeyGenerator.GetInstance(KeyProperties.KeyAlgorithmAes, ANDROID_KEYSTORE);

keygen.Init(new KeyGenParameterSpec.Builder(keyName, KeyStorePurpose.Encrypt | KeyStorePurpose.Decrypt)
keygen.Init(new KeyGenParameterSpec.Builder(key, KeyStorePurpose.Encrypt | KeyStorePurpose.Decrypt)
.SetBlockModes(KeyProperties.BlockModeCbc)
.SetEncryptionPaddings(KeyProperties.EncryptionPaddingPkcs7)
.SetUserAuthenticationRequired(true)
Expand All @@ -324,38 +324,38 @@ private BiometricPrompt.CryptoObject CreateCryptoObject(string keyName)

if (Logger.IsEnabled(LogLevel.Information))
{
Logger.LogInformation($"Successfully generated a symmetric pair (key name: '{keyName}').");
Logger.LogInformation($"Successfully generated a symmetric pair (key name: '{key}').");
}

cipher.Init(CipherMode.EncryptMode, _keyStore.GetKey(keyName, null));
cipher.Init(CipherMode.EncryptMode, _keyStore.GetKey(key, null));

return new BiometricPrompt.CryptoObject(cipher);
}

private BiometricPrompt.CryptoObject GetCryptoObject(string keyName, byte[] iv = null)
private BiometricPrompt.CryptoObject GetCryptoObject(string key, byte[] iv = null)
{
var cipher = Cipher.GetInstance(CIPHER_NAME);

if (_keyStore.IsKeyEntry(keyName))
if (_keyStore.IsKeyEntry(key))
{
try
{
cipher.Init(CipherMode.DecryptMode, _keyStore.GetKey(keyName, null), new IvParameterSpec(iv));
cipher.Init(CipherMode.DecryptMode, _keyStore.GetKey(key, null), new IvParameterSpec(iv));

return new BiometricPrompt.CryptoObject(cipher);
}
catch (KeyPermanentlyInvalidatedException)
{
if (Logger.IsEnabled(LogLevel.Error))
{
Logger.LogError($"Key '{keyName}' has been permanently invalidated.");
Logger.LogError($"Key '{key}' has been permanently invalidated.");
}

_keyStore.DeleteEntry(keyName);
_keyStore.DeleteEntry(key);

if (Logger.IsEnabled(LogLevel.Information))
{
Logger.LogInformation($"Permanently invalidated key '{keyName}' has been removed successfully.");
Logger.LogInformation($"Permanently invalidated key '{key}' has been removed successfully.");
}

throw new BiometryException(BiometryExceptionReason.KeyInvalidated, "Something went wrong while generating the CryptoObject used to decrypt.");
Expand All @@ -365,9 +365,9 @@ private BiometricPrompt.CryptoObject GetCryptoObject(string keyName, byte[] iv =
{
if (Logger.IsEnabled(LogLevel.Error))
{
Logger.LogError($"Key '{keyName}' not found.");
Logger.LogError($"Key '{key}' not found.");
}
throw new BiometryException(BiometryExceptionReason.KeyInvalidated, $"Key '{keyName}' not found.");
throw new BiometryException(BiometryExceptionReason.KeyInvalidated, $"Key '{key}' not found.");
}
}

Expand Down
Loading

0 comments on commit 8ca88df

Please sign in to comment.