diff --git a/ModernKeePassLib/Cryptography/ProtectedData.cs b/ModernKeePassLib/Cryptography/ProtectedData.cs index cf9dcd5..ea2aefd 100644 --- a/ModernKeePassLib/Cryptography/ProtectedData.cs +++ b/ModernKeePassLib/Cryptography/ProtectedData.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading.Tasks; using Windows.Security.Cryptography.DataProtection; using Windows.Storage.Streams; using ModernKeePassLib.Native; @@ -8,47 +9,62 @@ namespace ModernKeePassLib.Cryptography { public static class ProtectedData { - public static byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope) + public static async Task ProtectStream(byte[] buffer, IOutputStream stream) { - var provider = - new DataProtectionProvider(scope == DataProtectionScope.CurrentUser ? "LOCAL=user" : "LOCAL=machine"); - // Encode the plaintext input message to a buffer. - var buffMsg = userData.AsBuffer(); + //instantiate a DataProtectionProvider for decryption + var dpp = new DataProtectionProvider("LOCAL=user"); - // Encrypt the message. - IBuffer buffProtected; - try + //Open a stream to load data in + using (var inputStream = new InMemoryRandomAccessStream()) { - buffProtected = provider.ProtectAsync(buffMsg).GetAwaiter().GetResult(); + //cteate data writer to write data to the input stream + using (var dw = new DataWriter(inputStream)) + { + //write data to the stream + dw.WriteBuffer(buffer.AsBuffer()); + await dw.StoreAsync(); + + //encrypt the intput stream into the file stream + await dpp.ProtectStreamAsync(inputStream.GetInputStreamAt(0), + stream); + } } - catch (Exception e) - { - throw; - } - - return buffProtected.ToArray(); } - - public static byte[] Unprotect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope) + public static async Task UnprotectStream(IInputStream stream) { - var provider = - new DataProtectionProvider(scope == DataProtectionScope.CurrentUser ? "LOCAL=user" : "LOCAL=machine"); - // Decode the encrypted input message to a buffer. - var buffMsg = userData.AsBuffer(); + //instantiate a DataProtectionProvider for decryption + var dpp = new DataProtectionProvider(); - // Decrypt the message. - IBuffer buffUnprotected; - try + //create a stream to decrypte the data to + using (var outputStream = new InMemoryRandomAccessStream()) { - buffUnprotected = provider.UnprotectAsync(buffMsg).GetAwaiter().GetResult(); - } - catch (Exception e) - { - throw; - } + //decrypt the data + await dpp.UnprotectStreamAsync(stream, outputStream); - return buffUnprotected.ToArray(); + //fill the data reader with the content of the outputStream, + //but from position 0 + using (var dr = new DataReader(outputStream.GetInputStreamAt(0))) + { + //load data from the stream to the dataReader + await dr.LoadAsync((uint)outputStream.Size); + + //load the data from the datareader into a buffer + IBuffer data = dr.ReadBuffer((uint)outputStream.Size); + + return data.ToArray(); + } + } + } + + public static byte[] Unprotect(byte[] pbEnc, byte[] mPbOptEnt, DataProtectionScope currentUser) + { + throw new NotImplementedException(); + } + + public static byte[] Protect(byte[] pbPlain, byte[] mPbOptEnt, DataProtectionScope currentUser) + { + throw new NotImplementedException(); } } } diff --git a/ModernKeePassLib/Keys/KcpUserAccount.cs b/ModernKeePassLib/Keys/KcpUserAccount.cs index 802b503..e63117e 100644 --- a/ModernKeePassLib/Keys/KcpUserAccount.cs +++ b/ModernKeePassLib/Keys/KcpUserAccount.cs @@ -20,6 +20,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Runtime.InteropServices.WindowsRuntime; using System.Security; #if ModernKeePassLib @@ -67,9 +68,9 @@ namespace ModernKeePassLib.Keys { // Test if ProtectedData is supported -- throws an exception // when running on an old system (Windows 98 / ME). - byte[] pbDummyData = new byte[128]; + /*byte[] pbDummyData = new byte[128]; ProtectedData.Protect(pbDummyData, m_pbEntropy, - DataProtectionScope.CurrentUser); + DataProtectionScope.CurrentUser);*/ byte[] pbKey = LoadUserKey(false); if(pbKey == null) pbKey = CreateUserKey(); @@ -118,18 +119,16 @@ namespace ModernKeePassLib.Keys { string strFilePath = GetUserKeyFilePath(false); #if ModernKeePassLib - byte[] pbProtectedKey; - using (var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult() - .OpenStreamForReadAsync().GetAwaiter().GetResult()) + var file = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult(); + using (var fileStream = file.OpenReadAsync().GetAwaiter().GetResult()) { - pbProtectedKey = new byte[(int) fileStream.Length]; - fileStream.Read(pbProtectedKey, 0, (int) fileStream.Length); + pbKey = ProtectedData.UnprotectStream(fileStream).GetAwaiter().GetResult(); } #else byte[] pbProtectedKey = File.ReadAllBytes(strFilePath); -#endif - pbKey = ProtectedData.Unprotect(pbProtectedKey, m_pbEntropy, + pbKey = ProtectedData.Unprotect(pbProtectedKey, m_pbEntropy, DataProtectionScope.CurrentUser); +#endif } catch(Exception) { @@ -149,19 +148,19 @@ namespace ModernKeePassLib.Keys string strFilePath = GetUserKeyFilePath(true); byte[] pbRandomKey = CryptoRandom.Instance.GetRandomBytes(64); - byte[] pbProtectedKey = ProtectedData.Protect(pbRandomKey, - m_pbEntropy, DataProtectionScope.CurrentUser); #if ModernKeePassLib - using (var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult() - .OpenStreamForWriteAsync().GetAwaiter().GetResult()) + var file = ApplicationData.Current.RoamingFolder.CreateFileAsync(UserKeyFileName, CreationCollisionOption.ReplaceExisting).GetAwaiter().GetResult(); + using (var fileStream = file.OpenAsync(FileAccessMode.ReadWrite).GetAwaiter().GetResult()) { - fileStream.Write(pbProtectedKey, 0, (int) fileStream.Length); + ProtectedData.ProtectStream(pbRandomKey, fileStream).GetAwaiter().GetResult(); } #else + byte[] pbProtectedKey = ProtectedData.Protect(pbRandomKey, + m_pbEntropy, DataProtectionScope.CurrentUser); File.WriteAllBytes(strFilePath, pbProtectedKey); #endif - byte[] pbKey = LoadUserKey(true); + byte[] pbKey = LoadUserKey(true); Debug.Assert(MemUtil.ArraysEqual(pbKey, pbRandomKey)); MemUtil.ZeroByteArray(pbRandomKey);