社内の人にテストしてもらった結果Android2.3端末だけNGだった為、同エミュレータを使って確認してみると、あるデータを複合化する際にjavax.crypto.BadPaddingException が発生している事がわかりました。この例外の説明を読んでも意味不明なのですが、早い話『こんな鍵つかえねーよ』って所でしょうか?
暗号化/復号化の部分はググって一番初めに出てきた 『Hacking My Way ~ itogのhack日記 』を参考にしています。勿論これはあくまでサンプルですし、何の問題も無いと思います。
ここに掲載されているサンプルには、SecretKeySpec のコンストラクタに与えるバイト配列を生成する為のメソッド「getRawKey」があります。
private static byte[] getRawKey(byte[] seed) throws Exception { KeyGenerator keygen = KeyGenerator.getInstance("AES"); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); random.setSeed(seed);//これを消すと毎回ランダムになる keygen.init(128, random); SecretKey key = keygen.generateKey(); byte[] raw = key.getEncoded(); return raw; }これは同じバイト配列を種として使うと、生成されるバイト配列は毎度同じになりますが、Android2.2と2.3では結果が違う為、この動作を期待した実装をすると困る場合もあるよ、というお話でした。
…なんの事かわかりませんね。
トラノマキのライセンス認証では、あらかじめ暗号化したデータをサーバーに持たせておき、これを受け取って復号化するのですが、その『あらかじめ』暗号化する際に上記コードを使って鍵を生成している為、開発環境と同じ2.2では復号化できて、それ以外では失敗してしまう、という事でした。
対策としてライセンス認証の部分だけ乱数を使わない鍵で暗号/復号化するようにしました(ついでに違うアルゴリズムに変更)
以下は復号化部分
public static String decrypt(String seed, String encrypted) throws Exception { byte[] enc = Base64.decode(encrypted.getBytes(), Base64.DEFAULT); KeySpec keySpec = new PBEKeySpec(seed.toCharArray(), "Hoge".getBytes(), 1024,256); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHAAND256BITAES-CBC-BC"); SecretKey key = factory.generateSecret(keySpec); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec("Hage".getBytes())); byte[] result = cipher.doFinal(enc); return new String(result); }
0 件のコメント:
コメントを投稿