Encryption
Introduction
Laravel의 암호화 서비스는 OpenSSL을 활용하여 AES-256 및 AES-128 알고리즘으로 텍스트를 암호화하고 복호화할 수 있는 단순하고 편리한 인터페이스를 제공합니다. Laravel에서 암호화된 모든 값은 메시지 인증 코드(MAC)를 이용해 서명되므로, 암호화된 이후에는 해당 값이 임의로 변조되거나 수정될 수 없습니다.
Configuration
Laravel의 암호화기를 사용하기 전에 먼저 config/app.php 설정 파일의 key 설정 옵션을 지정해야 합니다. 이 설정 값은 APP_KEY 환경 변수에 의해 결정됩니다. php artisan key:generate 명령어를 사용하여 이 변수의 값을 생성하는 것이 좋습니다. key:generate 명령어는 PHP의 보안 난수 생성기를 활용하여 암호학적으로 안전한 암호화 키를 만들어주기 때문입니다. 보통은 Laravel's installation에서 APP_KEY 환경 변수 값이 자동으로 생성됩니다.
Gracefully Rotating Encryption Keys
애플리케이션의 암호화 키를 변경하면, 인증된 모든 사용자 세션이 강제로 로그아웃됩니다. 이는 모든 쿠키, 세션 쿠키를 포함해, Laravel이 암호화해서 저장하기 때문입니다. 또한, 이전 암호화 키로 암호화된 데이터는 더 이상 복호화할 수 없게 됩니다.
이 문제를 완화하기 위해, Laravel에서는 이전에 사용하던 암호화 키들을 애플리케이션의 APP_PREVIOUS_KEYS 환경 변수에 나열할 수 있도록 지원합니다. 이 변수에는 이전에 사용했던 모든 암호화 키를 콤마(,)로 구분하여 나열하면 됩니다.
APP_KEY="base64:J63qRTDLub5NuZvP+kb8YIorGS6qFYHKVo6u7179stY="
APP_PREVIOUS_KEYS="base64:2nLsGFGzyoae2ax3EF2Lyq/hH6QghBGLIq5uL+Gp8/w="
이 환경 변수를 지정하면, Laravel은 값을 암호화할 때 항상 "현재" 암호화 키를 사용합니다. 반면, 값을 복호화할 때는 우선 현재 키를 시도하고, 복호화에 실패하면 나열된 이전 키들을 차례대로 시도하여 정상적으로 복호화할 수 있을 때까지 진행합니다.
이런 방식으로 암호화 키를 무중단으로 교체하면, 암호화 키를 변경해도 사용자 입장에서는 별다른 불편 없이 애플리케이션을 계속 사용할 수 있습니다.
Using the Encrypter
Encrypting a Value
Crypt 파사드에서 제공하는 encryptString 메서드를 사용하여 값을 암호화할 수 있습니다. 저장되는 모든 값은 OpenSSL의 AES-256-CBC 암호화 방식을 사용하여 보호되고, 메시지 인증 코드(MAC)로 서명됩니다. 통합된 메시지 인증 기능 덕분에 악의적인 사용자가 값을 변조했다면, 해당 값의 복호화가 불가능해집니다.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
class DigitalOceanTokenController extends Controller
{
/**
* Store a DigitalOcean API token for the user.
*/
public function store(Request $request): RedirectResponse
{
$request->user()->fill([
'token' => Crypt::encryptString($request->token),
])->save();
return redirect('/secrets');
}
}
Decrypting a Value
Crypt 파사드의 decryptString 메서드를 사용해 암호화된 값을 복호화할 수 있습니다. 만약 메시지 인증 코드가 유효하지 않거나 값이 올바르게 복호화될 수 없는 경우, Illuminate\Contracts\Encryption\DecryptException 예외가 발생합니다.
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt;
try {
$decrypted = Crypt::decryptString($encryptedValue);
} catch (DecryptException $e) {
// ...
}