LoginSignup
16
19

More than 5 years have passed since last update.

AES256による暗号化/復号をPHPとJavaでやる

Last updated at Posted at 2017-06-19

お疲れ様です!
GMOリサーチの石黒です!

さて、皆さんも急にAESで暗号化したくなる衝動に駆られることがあると思います。
そんな皆さんのために今回は、JavaとPHP、PHPはOpenSSLとMcryptの、計3種類の方法で暗号化/複合のコードを書いていきます。
AES256アルゴリズム、ECBモード、PKCS5パディングで実装しています。

バージョン

Java 1.8
PHP 5.6

Java

Javaでは、デフォルトでAESの鍵の長さは128bitしか扱うことができません。
256bitの鍵を扱うためには、Javaのポリシーファイルを差し替える必要があります。

詳細はJavaでAES256を使用できるようにするなどの記事をご参照ください。

aes01.java
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

public class aes01 {

    public static void main(String[] args) {
        try {
            byte[] key = DatatypeConverter.parseBase64Binary(
                    "キーをbase64エンコードした文字列");
            SecretKeySpec sks = new SecretKeySpec(key, "AES");

            byte[] input = "暗号化したい文字列".getBytes();

            // 暗号化
            Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
            c.init(Cipher.ENCRYPT_MODE, sks);
            byte encrypted[] = c.doFinal(input);

            System.out.println(DatatypeConverter.printBase64Binary(encrypted));

            // 復号
            c.init(Cipher.DECRYPT_MODE, sks);
            byte decrypted[] = c.doFinal(encrypted);

            System.out.println(new String(decrypted));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

PHP(OpenSSL)

PHP5.3以降での暗号化はOpenSSLで行ないます。

aes01.php
<?php
$key = base64_decode("キーをbase64エンコードした文字列");

$input = '暗号化したい文字列';

// 暗号化
$encrypted = openssl_encrypt($input, 'aes-256-ecb', $key);

echo $encrypted;

// 復号
$decrypted = openssl_decrypt($encrypted, 'aes-256-ecb', $key);

echo $decrypted;

PHP(Mcrypt)※非推奨

非推奨な方法での暗号化です。
必要な時以外は使用しないようにしましょう。
というか面倒臭すぎます。

aes02.php
<?php
$key = base64_decode('キーをbase64エンコードした文字列');

$input = '暗号化したい文字列';

$crypt = new Crypt($key);

// 暗号化
$encrypted = base64_encode($crypt->encrypt($input));

echo $encrypted;

// 復号
$decrypted = $crypt->decrypt(base64_decode($encrypted));

echo $decrypted;

class Crypt {

    private $__encrypt_key = null;

    public $iv = null;

    public function __construct($encrypt_key) {
        $this->__encrypt_key = $encrypt_key;
    }

    public function encrypt($input, $algo = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_ECB) {
        list($size, $td) = $this->__open($algo, $mode);
        $input = $this->__pkcs5Pad($input, $size);
        $data = mcrypt_generic($td, $input);
        $this->__close($td);
        return $data;
    }

    public function decrypt($input, $algo = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_ECB) {
        list ($size, $td) = $this->__open($algo, $mode);
        $input = mdecrypt_generic($td, $input);
        $data = $this->__pkcs5Unpad($input);
        $this->__close($td);
        return $data;
    }

    private function __open($algo, $mode) {
        $size = mcrypt_get_block_size($algo, $mode);
        $td = mcrypt_module_open($algo, '', $mode, '');
        $this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $this->__encrypt_key, $this->iv);
        return array($size, $td);
    }

    private function __close($td){
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
    }

    public static function __pkcs5Pad($text, $blocksize) {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }

    public static function __pkcs5Unpad($text) {
        $pad = ord($text{strlen($text)-1});
        if ($pad > strlen($text)) return false;
        if (strspn($text, chr($pad), strlen($text) - $pad) !== $pad) return false;
        return substr($text, 0, -1 * $pad);
    }
}

MCRYPT_RIJNDAEL_128 というものが、AES256に相当するものらしいです。
MCRYPT_RIJNDAEL_256 というアルゴリズムもありますが、これではないので注意。

一応、汎用的に使えるよう、アルゴリズムとモードの変更はできるようになっていますが、
本当に使えるかは不明です。

おわりに

以上です!
これでAES暗号化したい衝動に駆られても大丈夫ですね。

PHPのOpenSSLが非常にシンプルで良かったと思いました。(小並感)

16
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
19