using Serilog;
using TINK.Model.Device;
namespace TINK.Services.BluetoothLock.Crypto
{
public class AuthCryptoHelper
{
private ICipher Cipher { get; }
/// Encrypted seed (random number) created inside ILOCKIT and passd to app.
private byte[] SeedLockEncrypted { get; }
/// Contstructs a auth crypto helper object.
/// Encrypted seed to deocode using .
/// Key used to to decrypt .
public AuthCryptoHelper(
byte[] seedLockEncrypted,
byte[] keyCopri,
ICipher cipher)
{
KeyCopri = keyCopri;
SeedLockEncrypted = seedLockEncrypted;
Cipher = cipher ?? new Cipher();
}
/// Public for testing purposes only.
public byte[] GetSeedLock()
{
byte[] seedLockDecrypted;
var seedLockEncrypted = SeedLockEncrypted;
var keyCopri = KeyCopri;
try
{
seedLockDecrypted = Cipher.Decrypt(
keyCopri,
seedLockEncrypted);
}
catch (System.Exception exception)
{
Log.ForContext().Error("Decrypting seed from lock failed. {Exception}", exception);
throw;
}
Log.ForContext().Verbose($"Lock random number decrypted from {string.Join(",", seedLockEncrypted)} to {string.Join(",", seedLockDecrypted)} using {string.Join(", ", keyCopri)}.");
return seedLockDecrypted;
}
public byte[] GetAccessKeyEncrypted()
{
var accessKey = GetSeedLock();
if (accessKey == null || accessKey.Length <= 0)
{
Log.ForContext().Error("Creating access key failed, Key must not be null or empty.");
throw new System.Exception();
}
accessKey[accessKey.Length - 1] += 1;
var keyCopri = KeyCopri;
byte[] acccessKeyEncrypted;
try
{
acccessKeyEncrypted = Cipher.Encrypt(
keyCopri,
accessKey);
}
catch (System.Exception exception)
{
Log.ForContext().Error("Encrypting access key failed. {Exception}", exception);
throw;
}
Log.ForContext().Verbose($"Access key encrypted from {string.Join(",", accessKey)} to {string.Join(",", acccessKeyEncrypted)} using {string.Join(", ", keyCopri)}.");
return acccessKeyEncrypted;
}
public byte[] KeyCopri { get; }
}
}