암호화 서비스

중요

비밀번호 저장에 이 라이브러리나 다른 암호화 라이브러리를 사용하지 마세요! 비밀번호는 반드시 해시해야 하며, PHP의 Password Hashing 확장을 통해 처리해야 합니다.

암호화 서비스는 양방향 대칭(비밀 키) 데이터 암호화를 제공합니다. 서비스는 아래에서 설명하는 매개변수에 맞는 암호화 핸들러를 인스턴스화 및/또는 초기화합니다.

암호화 서비스 핸들러는 CodeIgniter의 간단한 EncrypterInterface를 구현해야 합니다. 적절한 PHP 암호화 확장 또는 서드파티 라이브러리를 사용하려면 서버에 추가 소프트웨어를 설치해야 하거나 PHP 인스턴스에서 명시적으로 활성화해야 할 수 있습니다.

현재 지원되는 PHP 확장은 다음과 같습니다:

이것은 완전한 암호화 솔루션이 아닙니다. 공개 키 암호화 등 더 많은 기능이 필요하다면 OpenSSL을 직접 사용하거나 다른 암호화 확장을 고려해 보세요. Halite (libsodium 기반의 객체 지향 패키지)와 같은 보다 포괄적인 패키지도 또 다른 선택지입니다.

참고

MCrypt 확장에 대한 지원이 중단되었습니다. PHP 7.2부터 더 이상 사용되지 않기 때문입니다.

암호화 라이브러리 사용

CodeIgniter의 모든 서비스와 마찬가지로 Config\Services를 통해 로드할 수 있습니다:

<?php

$encrypter = service('encrypter');

시작 키를 설정했다면(라이브러리 설정 참조), 데이터 암호화 및 복호화는 간단합니다. 적절한 문자열을 encrypt() 및/또는 decrypt() 메서드에 전달하세요:

<?php

$plainText  = 'This is a plain-text message!';
$ciphertext = $encrypter->encrypt($plainText);

// Outputs: This is a plain-text message!
echo $encrypter->decrypt($ciphertext);

이것으로 끝입니다! 암호화 라이브러리는 전체 프로세스가 즉시 사용 가능한 수준의 암호화 보안을 갖추도록 필요한 모든 작업을 수행합니다. 걱정할 필요가 없습니다.

라이브러리 설정

위 예제는 app/Config/Encryption.php에 있는 설정을 사용합니다.

옵션

가능한 값 (기본값은 괄호 안에)

key

암호화 키 시작값

driver

선호하는 핸들러, 예: OpenSSL 또는 Sodium (OpenSSL)

digest

메시지 다이제스트 알고리즘 (SHA512)

blockSize

[SodiumHandler 전용] 바이트 단위 패딩 길이 (16)

cipher

[OpenSSLHandler 전용] 사용할 암호 (AES-256-CTR)

encryptKeyInfo

[OpenSSLHandler 전용] 암호화 키 정보 ('')

authKeyInfo

[OpenSSLHandler 전용] 인증 키 정보 ('')

rawData

[OpenSSLHandler 전용] 암호문이 원시 형식이어야 하는지 여부 (true)

Services 호출에 사용자 정의 설정 객체를 전달하여 설정 파일의 값을 대체할 수 있습니다. $config 변수는 Config\Encryption 클래스의 인스턴스여야 합니다.

<?php

use Config\Encryption;

$config         = config(Encryption::class);
$config->key    = 'aBigsecret_ofAtleast32Characters';
$config->driver = 'OpenSSL';

$encrypter = service('encrypter', $config);

CI3과의 호환성을 유지하기 위한 설정

Added in version 4.3.0.

v4.3.0부터 CI3의 암호화로 암호화된 데이터를 복호화할 수 있습니다. 이러한 데이터를 복호화해야 한다면 다음 설정을 사용하여 호환성을 유지하세요.

<?php

use Config\Encryption;

$config         = new Encryption();
$config->driver = 'OpenSSL';

// Your CI3's 'encryption_key'
$config->key = hex2bin('64c70b0b8d45b80b9eba60b8b3c8a34d0193223d20fea46f8644b848bf7ce67f');
// Your CI3's 'cipher' and 'mode'
$config->cipher = 'AES-128-CBC';

$config->rawData        = false;
$config->encryptKeyInfo = 'encryption';
$config->authKeyInfo    = 'authentication';

$encrypter = service('encrypter', $config);

지원되는 HMAC 인증 알고리즘

HMAC 메시지 인증을 위해 암호화 라이브러리는 SHA-2 계열 알고리즘 사용을 지원합니다:

알고리즘

원시 길이 (바이트)

16진수 인코딩 길이 (바이트)

SHA512

64

128

SHA384

48

96

SHA256

32

64

SHA224

28

56

MD5나 SHA1과 같은 다른 인기 알고리즘을 포함하지 않은 이유는 더 이상 충분히 안전하지 않다고 여겨지기 때문입니다. 따라서 그 사용을 권장하고 싶지 않습니다. 반드시 사용해야 한다면 PHP의 기본 hash_hmac() 함수를 통해 쉽게 사용할 수 있습니다.

물론 더 강력한 알고리즘이 등장하여 널리 사용 가능해지면 향후에 추가될 것입니다.

기본 동작

기본적으로 암호화 라이브러리는 OpenSSL 핸들러를 사용합니다. 해당 핸들러는 AES-256-CTR 알고리즘, 설정된 , SHA512 HMAC 인증을 사용하여 암호화합니다.

암호화 키 설정

암호화 키는 사용 중인 암호화 알고리즘이 허용하는 길이만큼 반드시 길어야 합니다. AES-256의 경우 256비트 또는 32바이트(문자) 길이입니다.

키는 가능한 한 무작위여야 하며, 일반 텍스트 문자열이나 해시 함수의 출력 등이어서는 안 됩니다. 적절한 키를 생성하려면 암호화 라이브러리의 createKey() 메서드를 사용할 수 있습니다.

<?php

// $key will be assigned a 32-byte (256-bit) random key
$key = \CodeIgniter\Encryption\Encryption::createKey();

// for the SodiumHandler, you can use either:
$key = sodium_crypto_secretbox_keygen();
$key = \CodeIgniter\Encryption\Encryption::createKey(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);

키는 app/Config/Encryption.php에 저장하거나, 자체 저장 메커니즘을 설계하여 암호화/복호화 시 동적으로 키를 전달할 수 있습니다.

app/Config/Encryption.php에 키를 저장하려면 파일을 열고 다음을 설정하세요:

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Encryption extends BaseConfig
{
    public $key = 'YOUR KEY';

    // ...
}

키 또는 결과 인코딩

createKey() 메서드는 이진 데이터를 출력하는데, 이는 다루기 어렵습니다(예: 복사-붙여넣기 시 손상될 수 있음). 그러므로 bin2hex() 또는 base64_encode를 사용하여 키를 더 편리하게 다룰 수 있습니다. 예시:

<?php

// Get a hex-encoded representation of the key:
$encoded = bin2hex(\CodeIgniter\Encryption\Encryption::createKey(32));

// Put the same value with hex2bin(),
// so that it is still passed as binary to the library:
$key = hex2bin('your-hex-encoded-key');

암호화 결과에도 동일한 기법이 유용할 수 있습니다:

<?php

// Encrypt some text & make the results text
$encoded = base64_encode($encrypter->encrypt($plaintext));

키 저장 시 접두사 사용

암호화 키를 저장할 때 두 가지 특수 접두사를 활용할 수 있습니다: hex2bin:base64:. 이 접두사가 키 값 앞에 바로 붙으면 Encryption이 키를 지능적으로 파싱하여 여전히 이진 문자열을 라이브러리에 전달합니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Encryption extends BaseConfig
{
    // In Encryption, you may use
    public $key = 'hex2bin:<your-hex-encoded-key>';
    // or
    public $key = 'base64:<your-base64-encoded-key>';
    // ...
}

마찬가지로 .env 파일에서도 이 접두사를 사용할 수 있습니다!

// For hex2bin
encryption.key = hex2bin:<your-hex-encoded-key>

// or
encryption.key = base64:<your-base64-encoded-key>

암호화 키 교체

Added in version 4.7.0.

보안 모범 사례나 규정 준수 요구 사항으로 암호화 키를 교체해야 할 때, previousKeys 설정 옵션을 사용하여 이전 키로 암호화된 데이터를 복호화하는 능력을 유지하면서 모든 새로운 암호화 작업에는 새 키를 사용할 수 있습니다.

동작 원리

  • 암호화는 항상 현재 key 값을 사용합니다

  • 복호화는 먼저 현재 key를 시도합니다

  • 복호화에 실패하면 자동으로 previousKeys의 각 키를 순서대로 시도합니다

  • 이를 통해 데이터 손실 없이 원활한 키 교체가 가능합니다

설정

app/Config/Encryption.php$previousKeys 속성에 이전 키를 추가하세요:

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Encryption extends BaseConfig
{
    public string $key = 'hex2bin:your_new_encryption_key_in_hex';

    public array|string $previousKeys = [
        'hex2bin:your_old_encryption_key_in_hex',
        'hex2bin:another_old_key_if_needed',
    ];

    // ... other config options
}

.env 파일 사용

쉼표로 구분된 목록을 사용하여 .env 파일(권장)에 이전 키를 설정할 수도 있습니다:

encryption.key = hex2bin:your_new_key
encryption.previousKeys = hex2bin:old_key_1,hex2bin:old_key_2

프레임워크는 쉼표로 구분된 문자열을 자동으로 배열로 파싱하여 각 키를 처리합니다.

키 교체 워크플로우

  1. 교체 전: key로 데이터를 암호화하고 복호화합니다

  2. 교체 시작: 현재 key 값을 previousKeys 배열로 이동하고 key에 새 값을 설정합니다

  3. 교체 중: 새 데이터는 새 key로 암호화되고, 기존 데이터는 previousKeys를 통해 복호화 가능합니다

  4. 데이터 재암호화 (선택 사항): 기존 데이터를 복호화하고 새 키로 재암호화합니다

  5. 교체 완료: 모든 데이터가 재암호화되면 previousKeys에서 이전 키를 제거합니다

중요

previousKeys 기능은 복호화 폴백 전용입니다. 모든 새로운 암호화 작업은 항상 현재 key를 사용합니다. encrypt() 또는 decrypt()$params 인수로 명시적 키를 전달하면 previousKeys 폴백이 사용되지 않습니다.

패딩

때로는 메시지의 길이가 그 내용에 대한 많은 정보를 제공할 수 있습니다. 메시지가 “yes”, “no”, “maybe” 중 하나라면, 메시지를 암호화해도 소용없습니다. 길이만 알아도 메시지 내용을 알 수 있기 때문입니다.

패딩은 길이를 주어진 블록 크기의 배수로 만들어 이 문제를 완화하는 기법입니다.

패딩은 libsodium의 기본 sodium_padsodium_unpad 함수를 사용하여 SodiumHandler에서 구현됩니다. 암호화 전에 평문 메시지에 추가되고 복호화 후에 제거되는 패딩 길이(바이트 단위)를 사용합니다. 패딩은 Config\Encryption$blockSize 속성을 통해 설정할 수 있습니다. 이 값은 0보다 커야 합니다.

중요

자체 패딩 구현을 만들지 않는 것이 좋습니다. 항상 라이브러리의 더 안전한 구현을 사용해야 합니다. 또한 비밀번호에는 패딩을 사용하지 마세요. 비밀번호 길이를 숨기기 위해 패딩을 사용하는 것은 권장하지 않습니다. 서버에 비밀번호를 전송하려는 클라이언트는 대신 해시해야 합니다(해시 함수의 단일 반복만으로도 충분합니다). 이렇게 하면 전송되는 데이터의 길이가 일정하며 서버가 비밀번호 사본을 쉽게 얻을 수 없습니다.

암호화 핸들러 참고 사항

OpenSSL 참고 사항

OpenSSL 확장은 오랫동안 PHP의 표준 구성 요소였습니다.

CodeIgniter의 OpenSSL 핸들러는 AES-256-CTR 암호를 사용합니다.

설정에서 제공하는 는 암호화용과 인증용 두 가지 다른 키를 파생하는 데 사용됩니다. 이는 HMAC 기반 키 파생 함수 (HKDF)로 알려진 기법을 통해 달성됩니다.

Sodium 참고 사항

Sodium 확장은 PHP 7.2.0부터 PHP에 기본으로 포함되어 있습니다.

Sodium은 종단 간 시나리오에서 비밀 메시지를 전송할 때 XSalsa20 알고리즘으로 암호화하고, Poly1305로 MAC을 처리하며, XS25519로 키 교환을 합니다. 대칭 암호화와 같이 공유 키를 사용하여 문자열을 암호화하거나 인증하려면 Sodium은 XSalsa20 알고리즘으로 암호화하고 HMAC-SHA512로 인증합니다.

메시지 길이

암호화된 문자열은 일반적으로 원본 평문 문자열보다 깁니다(암호에 따라 다름).

이는 암호 알고리즘 자체, 암호문 앞에 추가되는 초기화 벡터(IV), 마찬가지로 앞에 추가되는 HMAC 인증 메시지의 영향을 받습니다. 또한 암호화된 메시지는 사용 중인 문자 집합에 관계없이 저장 및 전송이 안전하도록 Base64로 인코딩됩니다.

데이터 저장 메커니즘을 선택할 때 이 점을 유념하세요. 예를 들어, 쿠키는 4K의 정보만 저장할 수 있습니다.

암호화 서비스 직접 사용

암호화 라이브러리 사용에서 설명한 대로 Services를 사용하는 대신(또는 추가로), “Encrypter”를 직접 생성하거나 기존 인스턴스의 설정을 변경할 수 있습니다.

<?php

// create an Encryption instance
$encryption = new \CodeIgniter\Encryption\Encryption();

// reconfigure an instance with different settings
$encrypter = $encryption->initialize($config);

$config는 반드시 Config\Encryption 클래스의 인스턴스여야 한다는 점을 기억하세요.

클래스 레퍼런스

class CodeIgniter\Encryption\Encryption
static createKey([$length = 32])
매개변수:
  • $length (int) – 출력 길이

반환:

지정된 길이의 의사 난수 암호화 키, 실패 시 false

반환 형식:

string

운영 체제의 소스(예: /dev/urandom)에서 무작위 데이터를 가져와 암호화 키를 생성합니다.

initialize([Encryption $config = null])
매개변수:
  • $config (Config\Encryption) – 설정 매개변수

반환:

CodeIgniter\Encryption\EncrypterInterface 인스턴스

반환 형식:

CodeIgniter\Encryption\EncrypterInterface

예외:

CodeIgniter\Encryption\Exceptions\EncryptionException

다른 설정을 사용하도록 라이브러리를 초기화(설정)합니다.

예시:

<?php

$encrypter = $encryption->initialize(['cipher' => 'AES-256-CTR']);

자세한 내용은 라이브러리 설정 섹션을 참조하세요.

interface CodeIgniter\Encryption\CodeIgniter\Encryption\EncrypterInterface
encrypt($data[, $params = null])
매개변수:
  • $data (string) – 암호화할 데이터

  • $params (array|string|null) – 설정 매개변수 (키)

반환:

암호화된 데이터

반환 형식:

string

예외:

CodeIgniter\Encryption\Exceptions\EncryptionException

입력 데이터를 암호화하여 암호문을 반환합니다.

두 번째 인수로 매개변수를 전달하면, $params가 배열인 경우 key 요소가 이 작업의 시작 키로 사용됩니다. 또는 시작 키를 문자열로 전달할 수도 있습니다.

SodiumHandler를 사용 중이고 런타임에 다른 blockSize를 전달하려면 $params 배열에 blockSize 키를 전달하세요.

예시:

<?php

$ciphertext = $encrypter->encrypt('My secret message');
$ciphertext = $encrypter->encrypt('My secret message', ['key' => 'New secret key']);
$ciphertext = $encrypter->encrypt('My secret message', ['key' => 'New secret key', 'blockSize' => 32]);
$ciphertext = $encrypter->encrypt('My secret message', 'New secret key');
$ciphertext = $encrypter->encrypt('My secret message', ['blockSize' => 32]);
decrypt($data[, $params = null])
매개변수:
  • $data (string) – 복호화할 데이터

  • $params (array|string|null) – 설정 매개변수 (키)

반환:

복호화된 데이터

반환 형식:

string

예외:

CodeIgniter\Encryption\Exceptions\EncryptionException

입력 데이터를 복호화하여 평문으로 반환합니다.

두 번째 인수로 매개변수를 전달하면, $params가 배열인 경우 key 요소가 이 작업의 시작 키로 사용됩니다. 또는 시작 키를 문자열로 전달할 수도 있습니다.

SodiumHandler를 사용 중이고 런타임에 다른 blockSize를 전달하려면 $params 배열에 blockSize 키를 전달하세요.

예시:

<?php

echo $encrypter->decrypt($ciphertext);
echo $encrypter->decrypt($ciphertext, ['key' => 'New secret key']);
echo $encrypter->decrypt($ciphertext, ['key' => 'New secret key', 'blockSize' => 32]);
echo $encrypter->decrypt($ciphertext, 'New secret key');
echo $encrypter->decrypt($ciphertext, ['blockSize' => 32]);