php의 데이터를 암호화/복호화하려면 어떻게 해야 합니까?
저는 현재 학생이고 PHP를 공부하고 있습니다.PHP로 데이터를 간단하게 암호화/복호화하려고 합니다.온라인 검색을 해봤는데 그중 몇 개는 꽤 혼란스러웠다.
제가 하려는 일은 다음과 같습니다.
이러한 필드(UserID, Fname, Lname, Email, Password)로 구성된 테이블이 있습니다.
가 원하는 를 암호화하고 나서할 수 ?sha256
(암호화 )/암호화 알고리즘이 아닌 경우)
하나 입니다.hash(sha256)
복호화 복호화 실장)을.hash(sha256)+salt)
객님,,,답답답답답답답답답 다다 다다다 사+++
서문
테이블 정의부터 시작합니다.
- UserID
- Fname
- Lname
- Email
- Password
- IV
변경된 내용은 다음과 같습니다.
- [ ]
Fname
,Lname
★★★★★★★★★★★★★★★★★」Email
OpenSSL에서 제공하는 대칭 암호를 사용하여 암호화됩니다. IV
필드에는 암호화에 사용되는 초기화 벡터가 저장됩니다.스토리지 요건은 사용하는 암호 및 모드에 따라 달라집니다.자세한 내용은 나중에 설명하겠습니다.Password
필드는 단방향 비밀번호 해시를 사용하여 해시됩니다.
암호화
암호 및 모드
최적의 암호화 암호와 모드를 선택하는 것은 이 답변의 범위를 벗어나지만 최종 선택은 암호화 키와 초기화 벡터의 크기에 영향을 미칩니다.이 게시물에서는 AES-256-CBC를 사용합니다.AES-256-CBC는 고정 블록사이즈가 16바이트, 키사이즈가 16바이트, 24바이트 또는 32바이트 중 하나입니다.
암호화 키
적절한 암호화 키는 신뢰할 수 있는 난수 생성기에서 생성된 이진 블럽입니다.다음 예제를 권장합니다(>= 5.3).
$key_size = 32; // 256 bits
$encryption_key = openssl_random_pseudo_bytes($key_size, $strong);
// $strong will be true if the key is crypto safe
이 작업은 한 번 또는 여러 번 수행할 수 있습니다(암호 키 체인을 작성하려는 경우).이것들은 가능한 한 비공개로 해 주세요.
IV
초기화 벡터는 암호화에 랜덤성을 추가하여 CBC 모드에 필요합니다.이러한 값은 1회(기술적으로는 암호화 키당 1회)만 사용하는 것이 이상적이므로 행의 임의의 부분을 갱신하면 재생성됩니다.
IV를 생성하는 데 도움이 되는 함수가 제공됩니다.
$iv_size = 16; // 128 bits
$iv = openssl_random_pseudo_bytes($iv_size, $strong);
예
앞의 해서 한 번 해 볼까요?앞의 명령어를 사용하여$encryption_key
★★★★★★★★★★★★★★★★★」$iv
블록 사이즈로 패딩해야 합니다.
function pkcs7_pad($data, $size)
{
$length = $size - strlen($data) % $size;
return $data . str_repeat(chr($length), $length);
}
$name = 'Jack';
$enc_name = openssl_encrypt(
pkcs7_pad($name, 16), // padded data
'AES-256-CBC', // cipher and mode
$encryption_key, // secret key
0, // options (not used)
$iv // initialisation vector
);
스토리지 요건
암호화된 출력은하려면 IV 등의 합니다.데이터베이스에 이러한 값을 보존하려면 다음과 같은 지정된 컬럼타입을 사용합니다.BINARY
★★★★★★★★★★★★★★★★★」VARBINARY
.
출력값은 IV와 마찬가지로 바이너리입니다.이 값을 MySQL에 저장하려면 또는 컬럼을 사용하는 것을 고려해 주십시오.이 옵션이 아닌 경우 또는 를 사용하여 바이너리 데이터를 텍스트 표현으로 변환할 수도 있습니다. 변환하려면 33%에서 100% 사이의 저장 공간이 더 필요합니다.
복호화
저장된 값의 복호화도 비슷합니다.
function pkcs7_unpad($data)
{
return substr($data, 0, -ord($data[strlen($data) - 1]));
}
$row = $result->fetch(PDO::FETCH_ASSOC); // read from database result
// $enc_name = base64_decode($row['Name']);
// $enc_name = hex2bin($row['Name']);
$enc_name = $row['Name'];
// $iv = base64_decode($row['IV']);
// $iv = hex2bin($row['IV']);
$iv = $row['IV'];
$name = pkcs7_unpad(openssl_decrypt(
$enc_name,
'AES-256-CBC',
$encryption_key,
0,
$iv
));
인증된 암호화
(암호키와는 다른) 비밀키와 암호 텍스트에서 생성된 서명을 추가하여 생성된 암호 텍스트의 무결성을 더욱 향상시킬 수 있습니다.암호문이 복호화되기 전에 먼저 시그니처를 검증한다(가능한 한 고정시간 비교방법에 의해).
예
// generate once, keep safe
$auth_key = openssl_random_pseudo_bytes(32, $strong);
// authentication
$auth = hash_hmac('sha256', $enc_name, $auth_key, true);
$auth_enc_name = $auth . $enc_name;
// verification
$auth = substr($auth_enc_name, 0, 32);
$enc_name = substr($auth_enc_name, 32);
$actual_auth = hash_hmac('sha256', $enc_name, $auth_key, true);
if (hash_equals($auth, $actual_auth)) {
// perform decryption
}
다음 항목도 참조하십시오.
해싱
데이터베이스에 되돌릴 수 있는 비밀번호를 저장하는 것은 가능한 한 피해야 합니다.비밀번호의 내용을 확인하는 것이 아니라 비밀번호 확인만 하는 것이 좋습니다.사용자가 비밀번호를 분실한 경우 원래 비밀번호를 보내는 것보다 비밀번호를 재설정할 수 있도록 허용하는 것이 좋습니다(패스워드 재설정은 제한된 시간 동안만 수행 가능).
해시함수의 적용은 일방적인 조작이며, 그 후 원래의 데이터를 공개하지 않고 검증에 안전하게 사용할 수 있습니다.비밀번호의 경우 비교적 짧은 길이와 다수의 사용자가 패스워드를 선택할 수 없기 때문에 brute force 방식은 해시함수를 공개하는 실현 가능한 방법입니다.
MD5 또는 SHA1 등의 해시 알고리즘이 기존의 해시 값에 대해 파일 내용을 검증하도록 작성되었습니다.이러한 검증은 정확하면서도 신속하게 이루어지도록 크게 최적화되어 있습니다.상대적으로 제한된 출력 공간 때문에 알려진 암호와 각각의 해시 출력인 무지개 테이블을 사용하여 데이터베이스를 구축하는 것은 쉬웠습니다.
해시하기 전에 패스워드에 소금을 추가하면 무지개 테이블이 무용지물이 되지만 최근 하드웨어의 진보로 인해 무차별적인 강제 검색이 실현 가능한 접근법이 되었습니다.따라서 해싱 알고리즘은 의도적으로 느리고 최적화가 불가능해야 합니다.또, 기존의 패스워드 해시를 검증하는 기능에 영향을 주지 않고, 고속의 하드웨어에 대한 부하를 높일 수 있어 장래에 대비할 수 있습니다.
현재 인기 있는 두 가지 선택지가 있습니다.
- PBKDF2(패스워드 기반 키 파생 기능 v2)
- bcrypt(복어라고도 함)
이 답변에서는 bcrypt의 예를 사용합니다.
시대
패스워드 해시는 다음과 같이 생성할 수 있습니다.
$password = 'my password';
$random = openssl_random_pseudo_bytes(18);
$salt = sprintf('$2y$%02d$%s',
13, // 2^n cost factor
substr(strtr(base64_encode($random), '+', '.'), 0, 22)
);
$hash = crypt($password, $salt);
소금은 로 생성되어 랜덤한 데이터 덩어리를 형성하고, 그 후 를 통해 실행됩니다.base64_encode()
★★★★★★★★★★★★★★★★★」strtr()
을 맞추다[A-Za-z0-9/.]
.
함수는 알고리즘을 기반으로 해시를 수행합니다( ).$2y$
복어 (3GHz) 0.40)22 。
확인
사용자 정보가 포함된 행을 가져오면 다음 방법으로 비밀번호를 검증합니다.
$given_password = $_POST['password']; // the submitted password
$db_hash = $row['Password']; // field with the password hash
$given_hash = crypt($given_password, $db_hash);
if (isEqual($given_hash, $db_hash)) {
// user password verified
}
// constant time string compare
function isEqual($str1, $str2)
{
$n1 = strlen($str1);
if (strlen($str2) != $n1) {
return false;
}
for ($i = 0, $diff = 0; $i != $n1; ++$i) {
$diff |= ord($str1[$i]) ^ ord($str2[$i]);
}
return !$diff;
}
하려면 , 「」를 합니다.crypt()
이전에 계산된 해시를 소금값으로 전달합니다.지정된 비밀번호가 해시와 일치할 경우 반환값은 동일한 해시를 생성합니다.해시를 확인하려면 타이밍 공격을 피하기 위해 상수 시간 비교 함수를 사용하는 것이 좋습니다.
PHP 5.5를 사용한 암호 해시
PHP 5.5에는 위의 해시 방법을 단순화하기 위해 사용할 수 있는 패스워드 해시 함수가 도입되었습니다.
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 13]);
그리고 확인:
if (password_verify($given_password, $db_hash)) {
// password valid
}
참고 항목: ,
이 대답은 전에도 했던 것 같은데...하지만 데이터를 암호화/복호화하려면 SHA256을 사용할 수 없습니다.
//Key
$key = 'SuperSecretKey';
//To Encrypt:
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, 'I want to encrypt this', MCRYPT_MODE_ECB);
//To Decrypt:
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_ECB);
답변 배경 및 설명
이 질문을 이해하려면 먼저 SHA256이 무엇인지 이해해야 합니다.SHA256은 암호화 해시 함수입니다.암호화 해시 함수는 단방향 함수로 출력이 암호화적으로 안전합니다.즉, 해시(데이터 암호화와 동일)를 계산하기는 쉽지만 해시(데이터 복호화와 동일)를 사용하여 원래 입력을 얻기는 어렵습니다.암호화 해시 함수를 사용하면 복호화가 계산상 불가능하므로 SHA256을 사용하여 복호화를 수행할 수 없습니다.
사용하고 싶은 것은 쌍방향 함수, 구체적으로는 블록 암호입니다.데이터의 암호화와 복호화를 모두 가능하게 하는 기능.기능mcrypt_encrypt
★★★★★★★★★★★★★★★★★」mcrypt_decrypt
기본적으로 Blowfish 알고리즘을 사용합니다.PHP의 mcrypt 사용은 이 설명서에서 확인할 수 있습니다.암호 mcrypt에서 사용하는 암호 정의 목록도 있습니다.복어에 관한 위키는 위키피디아에서 찾을 수 있다.블록 암호는 기존의 크기 및 위치의 블록 입력을 기존의 키로 암호화하여 나중에 키를 사용하여 데이터를 복호화할 수 있도록 한다.이것이 SHA256이 제공할 수 없는 것입니다.
코드
$key = 'ThisIsTheCipherKey';
$ciphertext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, 'This is plaintext.', MCRYPT_MODE_CFB);
$plaintext = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $encrypted, MCRYPT_MODE_CFB);
openssl_encrypt를 사용하는 예를 다음에 나타냅니다.
//Encryption:
$textToEncrypt = "My Text to Encrypt";
$encryptionMethod = "AES-256-CBC";
$secretHash = "encryptionhash";
$iv = mcrypt_create_iv(16, MCRYPT_RAND);
$encryptedText = openssl_encrypt($textToEncrypt,$encryptionMethod,$secretHash, 0, $iv);
//Decryption:
$decryptedText = openssl_decrypt($encryptedText, $encryptionMethod, $secretHash, 0, $iv);
print "My Decrypted Text: ". $decryptedText;
function my_simple_crypt( $string, $action = 'e' ) {
// you may change these values to your own
$secret_key = 'my_simple_secret_key';
$secret_iv = 'my_simple_secret_iv';
$output = false;
$encrypt_method = "AES-256-CBC";
$key = hash( 'sha256', $secret_key );
$iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );
if( $action == 'e' ) {
$output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) );
}
else if( $action == 'd' ){
$output = openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv );
}
return $output;
}
는 하면 false
「」를 하고 있는 openssl_decrypt()
을 사용하다
// cryptographic key of a binary string 16 bytes long (because AES-128 has a key size of 16 bytes)
$encryption_key = '58adf8c78efef9570c447295008e2e6e'; // example
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
$encrypted = openssl_encrypt($plaintext, 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, $iv);
$encrypted = $encrypted . ':' . base64_encode($iv);
// decrypt to get again $plaintext
$parts = explode(':', $encrypted);
$decrypted = openssl_decrypt($parts[0], 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, base64_decode($parts[1]));
암호화된 문자열을 URL 경유로 전달할 경우 문자열을 urlencode해야 합니다.
$encrypted = urlencode($encrypted);
진행 상황을 더 잘 이해하려면 다음을 참조하십시오.
- http://blog.turret.io/the-missing-php-aes-encryption-example/
- http://thefsb.tumblr.com/post/110749271235/using-opensslendecrypt-in-php-
16 바이트 길이의 키를 생성하려면 다음을 사용합니다.
$bytes = openssl_random_pseudo_bytes(16);
$hex = bin2hex($bytes);
오류 openssl 을 합니다.echo openssl_error_string();
도움이 됐으면 좋겠다.
언급URL : https://stackoverflow.com/questions/10916284/how-to-encrypt-decrypt-data-in-php
'source' 카테고리의 다른 글
웹 사이트에서 현재 연도를 인쇄하는 가장 빠른 방법 (0) | 2022.10.30 |
---|---|
내부 클래스에서 외부 클래스 함수를 호출합니다. (0) | 2022.10.30 |
Node.js module.exports의 목적은 무엇이며 어떻게 사용합니까? (0) | 2022.10.29 |
Python에서만 datetime 개체를 날짜 문자열로 변환 (0) | 2022.10.29 |
어레이의 첫 번째 아이템 삭제(스택에서 팝핑 등) (0) | 2022.10.29 |