프로그래밍/PHP

[PHP] openssl encrypt/decrypt 사용시, OPENSSL_NO_PADDING 옵션에 대하여

채윤아빠 2020. 6. 8. 21:32
728x90
반응형

 

openssl의 대칭키 암/복호화를 이용할 때, 패딩 관련하여 헷갈릴 수 있는 부분이 있어 정리해 둡니다.

 

openssl_encrypt() 함수의 대칭키 암호화 결과 길이가 원문(plain text)와 다른 경우가 발생하는데, 이는 대칭키 암호화는 알고리즘의 블록 크기 (Block Size)가 맞아야 암/복호하가 수행되기 때문입니다.
암호화 결과는 패딩이 추가되어 블록 크기 (Block Size)의 배수에 맞게 길이가 조정됩니다. 즉 원문의 길이가 5이고, 블록 크기 (Block Size)가 8이면 3개의 패딩이 추가되어 길이가 8인 암호화 결과가 반환됩니다. 동일한 환경에서 원문의 길이가 블록 크기 (Block Size)의 배수인 경우에는 무조건 8만큼 추가로 패딩이 됩니다.


원문을 8바이트 입력하여 암호화하면 16바이트가 반환됩니다. 블록 크기의 배수에 해당하는 문자열을 입력하였을 때, 패딩이 추가되지 않도록 하려면, OPENSSL_NO_PADDING 옵션을 추가하여 openssl_encrypt() 함수를 호출해야만 합니다.


    $plain_text = '1234567890123456';
    $cipher = "AES-256-CBC";
    $key = "keykeykeykeykey.";

    $ivlen = openssl_cipher_iv_length($cipher);
    $iv = substr("1234567890123456789012345678901234567890123456789012345678901234567890", 0, $ivlen);

    $encrypted_data = openssl_encrypt($plain_text, $cipher, $key, OPENSSL_RAW_DATA, $iv);
    echo "encrypted data = " . bin2hex($encrypted_data) . "\n";

    $decrypted_data = openssl_decrypt($encrypted_data, $cipher, $key, OPENSSL_RAW_DATA, $iv);
    echo "decrypted data = " . $decrypted_data . "\n";

    $encrypted_data = openssl_encrypt($plain_text, $cipher, $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);
    echo "no padding encrypted data = " . bin2hex($encrypted_data) . "\n";

    $decrypted_data = openssl_decrypt($encrypted_data, $cipher, $key, OPENSSL_RAW_DATA, $iv);
    echo "no padding decrypted data(no option) = " . $decrypted_data . "\n";
    $decrypted_data = openssl_decrypt($encrypted_data, $cipher, $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv);
    echo "no padding decrypted data = " . $decrypted_data . "\n";

위 예제 소스를 보시면, OPENSSL_NO_PADDING 옵션을 추가한 경우와 그렇지 않은 경우를 비교해 놓았습니다.
위 예제를 실행한 결과입니다. 참고로 "AES-256-CBC" 알고리즘의 블록 크기는 16바이트 입니다.


encrypted data = 5ec1bb87e30bbe12cc8054a1e32f7e31edb72e0a57b1575f34194d1c825adab5
decrypted data = 1234567890123456
no padding encrypted data = 5ec1bb87e30bbe12cc8054a1e32f7e31
no padding decrypted data(no option) =
no padding decrypted data = 1234567890123456

입력한 원문의 길이가 16바이트로 "AES-256-CBC" 알고리즘의 블록 크기의 배수로 딱 떨어지게 되면, OPENSSL_NO_PADDING 옵션을 추가하지 않은 경우 패딩이 추가되어 암호화 결과는 32바이트가 반환됩니다.
반면에 OPENSSL_NO_PADDING 옵션을 추가한 경우에는 입력한 원문과 동일한 16바이트의 암호화된 결과가 반환됩니다.


주의할 점은 OPENSSL_NO_PADDING 옵션을 추가한 경우에는 복화화를 위한 openssl_decrypt() 함수 호출시에도 동일하게 OPENSSL_NO_PADDING 옵션을 추가해 주어야만 정상적으로 복호화가 수행됩니다. 또한 입력하는 원문의 길이도 알고리즘의 블록 크기의 배수여야만 정상적으로 암/복호화가 수행됩니다.

 

참고자료