暗号化調査3 : Crypto.getCipher メソッドの利用 : DES, AES 修正版
前回の記事「暗号化調査2 : as3crypto ←→ PyCrypto : DES, AES, RSA」を元に、as3 と python とで暗号化通信を行うサンプル制作を進めていた所、PyCrypto 側で DES 暗号化したデータを as3crypto 側で DES 復号できないケースがある事に気づきました。
8 byte 丁度の文字列は DES 復号可能でしたが、16 byte といった 8 byte より大きな文字列の復号が正常に行われませんでした。
調査の結果、AS3 版 SymmetricCrypter クラス内に問題があったため以下のように修正を行いました。
package com.dango_itimi.crypto { import com.hurlant.crypto.symmetric.IPad; import com.hurlant.crypto.symmetric.NullPad; import com.hurlant.crypto.symmetric.ICipher; import com.hurlant.crypto.Crypto; import com.hurlant.util.Base64; import com.hurlant.util.Hex; import flash.utils.ByteArray; public class SymmetricCrypter { private var crypter:ICipher; public static function createDESCrypter(key:String):SymmetricCrypter { return new SymmetricCrypter("des-ecb", key, new NullPad()); } public static function createAESCrypter(key:String):SymmetricCrypter { return new SymmetricCrypter("aes-128-ecb", key, new NullPad()); } public function SymmetricCrypter(cipherName:String, key:String, pad:IPad = null) { var keyBin:ByteArray = Hex.toArray(Hex.fromString(key)); crypter = Crypto.getCipher(cipherName, keyBin, pad); } public function encrypt(plainText:String):String { var textBin:ByteArray = Hex.toArray(Hex.fromString(plainText)); crypter.encrypt(textBin); var cipherText:String = Base64.encodeByteArray(textBin); return cipherText; } public function decrypt(cipherText:String):String { var decodedTextBin:ByteArray = Base64.decodeToByteArray(cipherText); crypter.decrypt(decodedTextBin); var decryptedText:String = Hex.toString(Hex.fromArray(decodedTextBin)); return decryptedText; } } }
DESKey, AESKey クラスインスタンスを直接作成するのではなく、Crypto クラスの getCipher メソッド経由で DES, AES 処理を行うためのクラスインスタンスを取得するように変更を行なっています。
Crypto.getCipher メソッド第一引数
Crypto.getCipher メソッド第一引数にどういった文字列を指定すればよいかは Crypto.getCipher メソッドのコメントに記述があります。
引用 : com.hurlant.crypto.Crypto クラス getCipher メソッドコメント
/** * Things that should work, among others: * "aes" * "aes-128-ecb" * "aes-128-cbc" * "aes-128-cfb" * "aes-128-cfb8" * "aes-128-ofb" * "aes-192-cfb" * "aes-256-ofb" * "blowfish-cbc" * "des-ecb" * "xtea" * "xtea-ecb" * "xtea-cbc" * "xtea-cfb" * "xtea-cfb8" * "xtea-ofb" * "rc4" * "simple-aes-cbc" */ public static function getCipher(name:String, key:ByteArray, pad:IPad=null):ICipher { … }
python 側では、DES 暗号化モード? に MODE_ECB と設定したので、as3 側でも同じく ECB モードに設定するために "des-ecb" という文字列を指定しました。
Crypto.getCipher メソッド第三引数の注意点
Crypto.getCipher メソッド第三引数には Padding 方法を指定します。
「AS3 Crypto Demo page」の Secret Key タブ内 Padding: 選択フォームを見ると「PKCS#5」「NONE」二種類の Padding 方法を選択できる事がわかります。Padding: に「NONE」を選択すると、前回作成した python 側での DES 暗号化した文字列の復号が可能となります。
Padding は「NONE」なのだから、Crypto.getCipher メソッド第三引数にデフォルトで設定されている null を指定すればよいのではないか、と考えてしまいそうですが、null を指定すると「PKCS#5」方式が選択されてしまう点にご注意ください。Padding に「NONE」を指定するには、NullPad クラスインスタンスを設定すればよいようです。
引用 : com.hurlant.crypto.symmetric.ECBMode クラスコンストラクタ 注意点
public function ECBMode(key:ISymmetricKey, padding:IPad = null) { this.key = key; if (padding == null) { padding = new PKCS5(key.getBlockSize()); } else { padding.setBlockSize(key.getBlockSize()); } this.padding = padding; }