이 문서는 AES-CBC 방식으로 토큰을 생성하는 방법을 설명합니다.
암호화를 위해 다음 써드파티 라이브러리를 사용합니다.
표준 AES 암호화 알고리즘과 PKCS7 패딩을 사용하므로, 같은 알고리즘을 제공하는 다른 라이브러리를 사용하셔도 구현이 가능합니다.
Copy import base64
import hashlib
import json
import os
import time
from cryptography . hazmat . backends import default_backend
from cryptography . hazmat . primitives import padding
from cryptography . hazmat . primitives . ciphers import Cipher , algorithms , modes
# 이 값은 예시를 위해 임의로 설정된 값입니다
CP_SECRET_KEY = '0123456789abcdefg'
def encrypt ( content : str , secret_key : str ) -> str :
key = hashlib . sha256 (secret_key. encode ( 'utf-8' )). digest () # SH256를 통해 CP_SECRET_KEY를 256-bit Key로 변환합니다.
iv = os . urandom ( 16 ) # 16-byte (128-bit) IV를 사용합니다.
padder = padding . PKCS7 ( 128 ). padder () # 128-bit PKCS7 padding을 사용합니다.
backend = default_backend () # 일반적으로 OpenSSL이 backend로 사용됩니다.
cipher = Cipher (algorithms. AES (key), modes. CBC (iv), backend = backend) # CBC 모드의 AES를 사용합니다.
encryptor = cipher . encryptor ()
content_padded = padder . update (content. encode ( 'utf-8' )) + padder . finalize ()
content_enc = encryptor . update (content_padded) + encryptor . finalize ()
return base64 . b64encode (iv + content_enc). decode ( 'utf-8' )
token_info = {
'uid' : 'test-user-1' ,
'fullname' : '김토끼' ,
'email' : 'tokki.kim@test.com' ,
'courseId' : 1234 ,
'ts' : int (time. time () * 1000 )
}
token = encrypt (json. dumps (token_info), CP_SECRET_KEY)
Copy using System ;
using System . Text ;
using System . Security . Cryptography ;
static String Encrypt ( String content , String secretKey)
{
using ( SHA256 sha256 = SHA256 . Create ())
using ( Aes aes = Aes . Create ())
{
byte [] iv = new byte [ 16 ];
rngCsp . GetBytes (iv);
aes . Key = sha256 . ComputeHash ( Encoding . UTF8 . GetBytes (secretKey));
aes . IV = iv;
aes . Mode = CipherMode . CBC ;
aes . Padding = PaddingMode . PKCS7 ;
byte [] contentBytes = Encoding . UTF8 . GetBytes (content);
byte [] contentEnc = aes . CreateEncryptor ()
. TransformFinalBlock (contentBytes , 0 , contentBytes . Length );
byte [] result = new byte [ iv . Length + contentEnc . Length ];
iv . CopyTo (result , 0 );
contentEnc . CopyTo (result , iv . Length );
return Convert . ToBase64String (result);
}
}
Copy import java . lang . System ;
import java . security . MessageDigest ;
import java . util . Base64 ; // JDK 8+ only
import java . util . Random ;
import javax . crypto . Cipher ;
import javax . crypto . spec . IvParameterSpec ;
import javax . crypto . spec . SecretKeySpec ;
import javax . xml . bind . DatatypeConverter ; // JDK 6, JDK 7 only
static String encrypt( String content , String secretKey) throws Exception {
byte [] iv = new byte [ 16 ];
new Random() . nextBytes (iv);
MessageDigest sha256 = MessageDigest . getInstance ( "SHA-256" );
sha256 . update ( secretKey . getBytes ( "UTF-8" ));
byte [] key = sha256 . digest ();
// JAVA 에서 PKCS5Padding 는 실제로는 PKCS7Padding 로 작동합니다.
Cipher aes = Cipher . getInstance ( "AES/CBC/PKCS5Padding" );
aes . init ( Cipher . ENCRYPT_MODE , new SecretKeySpec(key , "AES" ) , new IvParameterSpec(iv) );
byte [] contentBytes = content . getBytes ( "UTF-8" );
byte [] contentEnc = aes . doFinal (contentBytes , 0 , contentBytes . length );
byte [] result = new byte [ iv . length + contentEnc . length ];
System . arraycopy (iv , 0 , result , 0 , iv . length );
System . arraycopy (contentEnc , 0 , result , iv . length , contentEnc . length );
// JDK 8+ only
byte [] resultBase64 = Base64 . getEncoder () . encode (result);
return new String(resultBase64) ;
// // JDK 6, JDK 7
// return DatatypeConverter.printBase64Binary(result);
}
Copy {
"uid" : "test-user-1" ,
"fullname" : "김토끼" ,
"email" : "tokki.kim@test.com" ,
"ts" : 1586961104518
}