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
に通します。
こちらも誤ったパスワードで複合した際のチェックを行っていませんが、だいたいは解凍時におかしくなってエラーになるっぽいです。
全体のプロジェクト
暗号化されたテキストを読み書きできるツールを作ってみました。