반응형

Java 와 PHP 가 암호화 텍스트를 주고 받을 때 사용할 수 있는 코드를 공유합니다.

방식은 AES ECB NoPadding 입니다.


NoPadding 때문에 암호화 대상에 임의로 16바이트에 맞춰서 공백 문자열을 넣어주고 있는데,

자바는 empty byte를 php 는 공백 문자열을 넣어주고 있어서 동일한 값을 암호화한 결과가 다르게 나옵니다.

하지만 복호화는 서로 잘되니 문제없이 쓸수 있습니다.


아래 코드를 참고하셔서 테스트하시면 됩니다.


php 테스트 사이트 : http://phptester.net/

java 테스트 사이트 : https://www.compilejava.net/


Java Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
 
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
 
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
public class AES {
  public static byte[] ivBytes = { 0x000x000x000x000x000x000x000x000x000x000x000x000x000x00,
      0x000x00 };
 
  public static String encryptAes(String text, String key)
      throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
      IllegalBlockSizeException, BadPaddingException {
    if (text == null || text.length() == 0) {
      return text;
    }
    String encrypted = null;
    byte[] source = text.getBytes("UTF-8");
    SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
 
    Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    int mod = source.length % 16;
    byte[] changeSource = null;
    if (mod != 0) {
      changeSource = new byte[source.length + (16 - mod)];
      System.arraycopy(source, 0, changeSource, 0, source.length);
    } else {
      changeSource = source;
    }
    encrypted = byteArrayToHex(cipher.doFinal(changeSource));
    return encrypted;
  }
 
  // key는 16 바이트로 구성 되어야 한다.
  public static String decryptAES(String s, String key) throws NoSuchAlgorithmException, NoSuchPaddingException,
      InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
    if (s == null || s.length() == 0) {
      return s;
    }
    String decrypted = null;
    SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
 
    Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    decrypted = new String(cipher.doFinal(hexToByteArray(s)), "UTF-8");
    return decrypted.trim();
  }
 
  private static byte[] hexToByteArray(String s) {
    byte[] retValue = null;
    if (s != null && s.length() != 0) {
      retValue = new byte[s.length() / 2];
      for (int i = 0; i < retValue.length; i++) {
        retValue[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16);
      }
    }
    return retValue;
  }
 
  private static String byteArrayToHex(byte buf[]) {
    StringBuffer strbuf = new StringBuffer();
    for (int i = 0; i < buf.length; i++) {
      strbuf.append(String.format("%02X", buf[i]));
    }
 
    return strbuf.toString();
  }
 
  public static String encryptAES(String s, String key, String op1, String op2) throws Exception {
    String encrypted = null;
    SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), op1);
 
    Cipher cipher = Cipher.getInstance(op2);
    AlgorithmParameterSpec IVspec = new IvParameterSpec(ivBytes);
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, IVspec);
    // cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
 
    encrypted = byteArrayToHex(cipher.doFinal(s.getBytes("UTF-8")));
    return encrypted;
  }
 
  public static void main(String[] args) throws InvalidKeyException, UnsupportedEncodingException,
      NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
    System.out.println(encryptAes("abc""12345678901234561234567890123456"));
    System.out.println(decryptAES("26438AE1764AA2FA01C52C230321AA85""12345678901234561234567890123456"));
  }
}



Result

1
2
695CFBAA063C83469BDB25741E3EA278
abc



Php Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
class CryptAES 
{
    protected $cipher     = MCRYPT_RIJNDAEL_128;
    protected $mode       = MCRYPT_MODE_ECB;
    protected $pad_method = 'no';
    protected $secret_key = '';
    protected $iv         = '';
 
 
    public function set_cipher($cipher)
    {
        $this->cipher = $cipher; 
    }
 
    public function set_mode($mode)
    {
        $this->mode = $mode;
    }
 
    public function set_iv($iv)
    {
        $this->iv = $iv;
    }
 
    public function set_key($key)
    {
        $this->secret_key = $key;
    }
 
    protected function pad($str)
    {
        return $this->no_pad($str); 
    }
 
    protected function unpad($str)
    {
        return $this->no_unpad($str); 
    }
 
 
    public function encrypt($str)
    {
        $str = $this->pad($str);
        $td = mcrypt_module_open($this->cipher, '', $this->mode, '');
 
        if ( empty($this->iv) )
        {
            $iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        }
        else
        {
            $iv = $this->iv;
        }
 
        mcrypt_generic_init($td, $this->secret_key, $iv);
        $cyper_text = mcrypt_generic($td, $str);
        $rt = bin2hex($cyper_text);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
 
        return strtoupper($rt);
    }
 
 
    public function decrypt($str){
        $td = mcrypt_module_open($this->cipher, '', $this->mode, '');
 
        if ( empty($this->iv) )
        {
            $iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        }
        else
        {
            $iv = $this->iv;
        }
 
        mcrypt_generic_init($td, $this->secret_key, $iv);
        $decrypted_text = mdecrypt_generic($td, self::hex2bin($str));
        $rt = $decrypted_text;
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
 
        return $this->unpad($rt);
    }
 
    public static function hex2bin($hexdata) {
        $bindata = '';
        $length = strlen($hexdata);
        for ($i=0; $i < $length; $i += 2)
        {
            $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
        }
        return $bindata;
    }
 
    
    public static function no_pad($text)
    {
        $blocksize = 16;
        $pad = $blocksize - (strlen($text) % $blocksize);
        if($pad == 16){
            return $text;
        } else {
            return $text . str_repeat(' ', $pad);
        }
        
    }
 
    public static function no_unpad($text)
    {        
        return trim($text);
    }
}
$aes = new CryptAES();
$aes->set_key('12345678901234561234567890123456');
$rt = $aes->encrypt('abc');
echo $rt . '<br/>';
echo $aes->decrypt('695CFBAA063C83469BDB25741E3EA278') . '<br/>';


Result

1
2
26438AE1764AA2FA01C52C230321AA85
abc


반응형

+ Recent posts