//Load an encryption key from a file public void LoadKeyFromFile(string path) { if (_encryptionKey != null) { throw new KeyAlreadyLoadedException(); } //We don't know how .NET buffers things in memory, so we write it ourselves for maximum security //avoid excess buffering where possible, even if slow using (var file = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None)) { if (file.Length != KEYLENGTH * KEYCOUNT) { throw new InvalidKeyFileException(); } _encryptionKey = new SecureBuffer(KEYLENGTH); _hmacKey = new SecureBuffer(KEYLENGTH); foreach (var buffer in new [] { _encryptionKey.Buffer, _hmacKey.Buffer }) { int bytesRead = file.Read(buffer, 0, KEYLENGTH); if (bytesRead != KEYLENGTH) { throw new IOException("Unable to read from key file!"); } } } }
private EncryptedBlob Encrypt(SecureBuffer input) { EncryptedBlob blob; #if NETSTANDARD1_3 var aes = Aes.Create(); #elif NET20 || NET30 var aes = Rijndael.Create(); #else var aes = new AesCryptoServiceProvider(); #endif using (aes) { aes.Mode = CipherMode.CBC; aes.Key = _encryptionKey.Buffer; aes.BlockSize = 128; aes.GenerateIV(); blob.IV = aes.IV; using (var encryptor = aes.CreateEncryptor()) { blob.Payload = encryptor.TransformFinalBlock(input.Buffer, 0, input.Buffer.Length); } } blob.Hmac = Authenticate(blob.IV, blob.Payload); return(blob); }
/// <summary> /// Creates a new <see cref="SecureBuffer"/> to hold a copy of /// the data contained in <paramref name="insecure"/>. Does not /// offer any protection, but provides compatibility between /// <c>byte[]</c> and <c>SecureBuffer</c>. /// </summary> /// <param name="insecure"></param> /// <param name="offset"></param> /// <param name="length"></param> /// <returns></returns> public static SecureBuffer From(byte[] insecure, int offset = 0, int?length = null) { var buffer = new SecureBuffer(length ?? insecure.Length); Array.Copy(insecure, offset, buffer.Buffer, 0, length ?? insecure.Length); return(buffer); }
public T Retrieve <T>(string name) { using (var decrypted = new SecureBuffer(Decrypt(_vault.Data[name]))) { //the conversion from bytes to string involves some non-shredded memory return(JsonConvert.DeserializeObject <T>(Encoding.UTF8.GetString(decrypted.Buffer))); } }
public void LoadKey(SecureBuffer key) { if (key == null) { throw new ArgumentNullException("key"); } LoadKey(key.Buffer); }
public void Set <T>(string name, T value) { //JsonConvert and the UTF8 conversion likely involve non-shredded memory var insecure = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)); using (var secured = new SecureBuffer(insecure)) { _vault.Data[name] = Encrypt(secured); } }
//Generate a new key for a new store public void GenerateKey() { if (_encryptionKey != null) { throw new KeyAlreadyLoadedException(); } _encryptionKey = new SecureBuffer(KEYLENGTH); GenerateBytes(_encryptionKey.Buffer); _hmacKey = new SecureBuffer(KEYLENGTH); GenerateBytes(_hmacKey.Buffer); }
public void Dispose() { if (_hmacKey != null) { _hmacKey.Dispose(); _hmacKey = null; } if (_encryptionKey != null) { _encryptionKey.Dispose(); _encryptionKey = null; } }
//Derive an encryption key from a password public void LoadKeyFromPassword(string password) { if (_encryptionKey != null) { throw new KeyAlreadyLoadedException(); } var insecure = DerivePassword(password, _vault.IV); using (var sb = new SecureBuffer(insecure)) { SplitKey(insecure); } }
public SecureBuffer ExportKey() { if (_encryptionKey?.Buffer == null || _hmacKey?.Buffer == null) { throw new NoKeyLoadedException(); } var secure = new SecureBuffer(KEYLENGTH * 2); Array.Copy(_encryptionKey.Buffer, secure.Buffer, KEYLENGTH); Array.Copy(_hmacKey.Buffer, 0, secure.Buffer, KEYLENGTH, KEYLENGTH); return(secure); }
private void SplitKey(byte[] insecure) { //While the consensus is that AES and HMAC are "sufficiently different" that reusing //the same key for Encrypt-then-MAC is probably safe, it's not something provable //and therefore (esp. since we can without too much additional burden) we should use two //separate keys. using (var temp = new SecureBuffer(insecure)) { _encryptionKey = new SecureBuffer(KEYLENGTH); _hmacKey = new SecureBuffer(KEYLENGTH); Array.Copy(temp.Buffer, 0, _encryptionKey.Buffer, 0, KEYLENGTH); Array.Copy(temp.Buffer, KEYLENGTH, _hmacKey.Buffer, 0, KEYLENGTH); } }