C#
VisualStudio
aes
WindowsAPI

ユニバーサルアプリで暗号化

More than 3 years have passed since last update.

Windows API では、.NetのAPIから大きく変更されているようです。hibaraさんの記事を参考にしてみたのですが、AesManagedをはじめとしたクラスはユニバーサルWindowsアプリの開発では利用できませんでした。

そこで、記事を参考に同様のことをWindows APIで行ってみます。


暗号化

SymmetricAlgorithmNames.AesCbcPkcs7で取得したSymmetricKeyAlgorithmProviderを用いると、CBCでPKCS7なAES暗号を利用することができます。

private static readonly string ALGORITHM_NAME = SymmetricAlgorithmNames.AesCbcPkcs7;

private IBuffer toEncryptedBuffer(IBuffer buffer, string rawPassword, out IBuffer salt, out IBuffer iv)
{
// https://msdn.microsoft.com/en-us/library/windows/apps/windows.security.cryptography.core.symmetrickeyalgorithmprovider.aspx
SymmetricKeyAlgorithmProvider algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(ALGORITHM_NAME);

salt = CryptographicBuffer.GenerateRandom(32);
var derviedKey = createDerviedKey(algorithm, rawPassword, salt);

iv = CryptographicBuffer.GenerateRandom(algorithm.BlockLength);

return CryptographicEngine.Encrypt(derviedKey, buffer, iv);
}

createDerviedKeyメソッドではキーの生成を行います。元の記事では Rfc2898DeriveBytes を利用していますが、RFC2898とPBKDF2は同じアルゴリズムを指しています

private const uint SALT_ITERATION_COUNT = 10000;

private CryptographicKey createDerviedKey(SymmetricKeyAlgorithmProvider algorithm, string rawPassword, IBuffer salt)
{
KeyDerivationAlgorithmProvider pbkdf2 = KeyDerivationAlgorithmProvider.OpenAlgorithm(KeyDerivationAlgorithmNames.Pbkdf2Sha256);
IBuffer passwordBuffer = CryptographicBuffer.ConvertStringToBinary(rawPassword, BinaryStringEncoding.Utf8);
CryptographicKey key = pbkdf2.CreateKey(passwordBuffer);

KeyDerivationParameters parameters = KeyDerivationParameters.BuildForPbkdf2(salt, SALT_ITERATION_COUNT);

IBuffer derviedKeyMaterial = CryptographicEngine.DeriveKeyMaterial(key, parameters, 32);
return algorithm.CreateSymmetricKey(derviedKeyMaterial);
}

暗号化前に圧縮をかける定石は、これまで通りDeflateStreamが使えます。


複合

先ほどのcreateDerviedKeyを使ってほとんど似たようなコードで複合することができます。

private IBuffer toDecryptedBuffer(IBuffer buffer, string rawPassword, IBuffer salt, IBuffer iv)

{
SymmetricKeyAlgorithmProvider algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(ALGORITHM_NAME);

var derviedKey = createDerviedKey(algorithm, rawPassword, salt);

return CryptographicEngine.Decrypt(derviedKey, buffer, iv);
}

解凍はIBuffer.AsStream()を使ってStreamにした後にDeflateStreamに通します。

こちらも誤ったパスワードで複合した際のチェックを行っていませんが、だいたいは解凍時におかしくなってエラーになるっぽいです。


全体のプロジェクト

暗号化されたテキストを読み書きできるツールを作ってみました。

https://github.com/utisam/encedit