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; } } }