PHP PHP와 OpenSSL

황제낙엽 2007.09.27 21:55 Đã xem : 283 Bình chọn:71

sitelink1 http://www.ecoop.net/memo/2007-04-26-3.html 
sitelink2  
sitelink3  
sitelink4  
extra_vars5  
extra_vars6  

PHP에서 OpenSSL함수를 사용해 보았기에 定番のハロ?ワ?ルド에 놓아둡니다.

--------------------------------------------------------------------------------
OpenSSL 함수에서 암호화, 복호화를 실행하는데에는 암호화, 복호화에 필요한 키쌍을
PEM 형식으로 생성 할 필요가 있습니다.

1. 패스워드 비밀키 private_password.pem 를 생성

    $ openssl genrsa private_password.pem -des3 1024

2. (1)로부터 패스워드가 아닌 비밀키 private.pem 를 생성

    $ openssl rsa -in private_password.pem -out private.pem

3. (1)을 삭제

    $ rm private_password.pem

4. (2)로부터 공개키 public.pem 를 생성

    $ openssl rsa -in private.pem -pubout -out public.pem

--------------------------------------------------------------------------------
openssl_public_encrypt(), openssl_private_encrypt()
…공개키로 암호화하고, 비밀키로 복호화합니다.
즉, 누구라도 암호화하여 보낼 수 있습니다만, 내용을 읽을수 있는 것은
비밀키를 가지고 있는 사람만 되기에, 통신 경로에서의 도청이 불가능하게 되어,
내용이 외부에 새어 나갈 걱정이 없기 때문에 기밀성이 높아집니다.
단, 누구라도 암호화 할 수 있기에 암호화된 파일을 수정가능 하기에 신뢰성은 없습니다.

// 암호화에 사용하는 공개키
    $public_key = file_get_contents("public.pem");
 
// 암호화하는 문자열
    $message = "Hello, world!!";
 
// 암호화데이터의 결과저장변수
    $encrypted = "";
 
// 암호화실행
    if(!openssl_public_encrypt($message, $encrypted, $public_key)){
        echo "暗?化に失敗n";
        die;
    }
 
// 암호화결과를 표시(그대로는 표시할 수 없기에 BASE64엔코딩한다.)
    echo "暗?化デ?タ: n ".base64_encode($encrypted) . "n";
 
    $message = null;
// ---------------------
// 암호화
// ---------------------
// 암호화에 사용한 공개키에 대응하는 비밀키
    $private_key = file_get_contents("private.pem");
 
// 복호화 결과저장변수
    $result = "";
 
// 복호화 실행
    if(!openssl_private_decrypt($encrypted, $result, $private_key)){
        echo "復?化に失敗n";
        die;
    }
 
// 결과 출력
    echo "復?化結果: n " . $result . "n"
         "BASE64:n" . base64_encode($result)."n"; // 비교용


--------------------------------------------------------------------------------
결과
--------------------------------------------------------------------------------
暗?化デ?タ:
FmPaJ9jOmjl/mK249NqUPzYjPUHsmFkSuNyp0SMlgW1c9RRzmKXBjcRhXH/5fwTxItAcE8/
AlZkjYo27XvGR7a3hdXxgaXbk4VORdRRk8LJXKB+xlVzF48OlHJ5lKUrXUdfr2BFtx53/IH
431mBlYWDhf+KyW608eKAA0T34qRY=
復?化結果:
Hello, world!!
BASE64:
SGVsbG8sIHdvcmxkZmc=


 


--------------------------------------------------------------------------------
openssl_private_encrypt(), openssl_public_decrypt() 의 예:
…비밀키로 암호화하고, 공개키로 복호화합니다.
즉, 키의 소유자밖에 암호화할 수 없기에 내용의 변경도, 유출경로의 변경도 불가능하여
내용에 대한 신뢰성이 높아집니다.
단, 누구라도 읽을 수 있기때문에 내용의 기밀성이 떨어집니다.
 
소스에서는 비밀키, 공개키의 사용방법을 역으로 하는것 이외에는 위의 예와 동일합니다.

// 암호화에 사용하는 비밀키
    $private_key = file_get_contents("private.pem");
 
// 암호화하는 문자열
    $message = "Hello, world!!";
 
// 암호화데이터의 결과저장변수
    $encrypted = "";
 
// 암호화 실행
    if(!openssl_private_encrypt($message, $encrypted, $private_key)){
        echo "暗?化に失敗n";
        die;
    }
 
// 암호화 결과를 표시 (그대로는 표시할 수 없기 때문에 BASE64로 엔코딩한다.)
    echo "暗?化デ?タ: n ".base64_encode($encrypted) . "n";
 
    $message = null;
// ---------------------
// 복호화
// ---------------------
// 암호화에 사용하는 비밀키로부터 만든 공개키
    $public_key = file_get_contents("public.pem");
 
// 복호화 결과저장변수
    $result = "";
 
// 복호화 실행
    if(!openssl_public_decrypt($encrypted, $result, $public_key)){
        echo "復?化に失敗n";
        die;
    }
 
// 결과 출력
    echo "復?化結果: n " . $result . "n"
         "BASE64:n" . base64_encode($result)."n"; // 比較用


--------------------------------------------------------------------------------
결과
--------------------------------------------------------------------------------
暗?化デ?タ:
CII4EW6LQBq0faVJxshUfk9VCdFsE66DnQPVdsLbvfq7tNCMzAIZbZA3GBxHu4cG2TqvOnn
xN9C9S9IgBIbulfj4c90IkrYtHQGt3RHAJBYiAgfmzCKbMr2cPJhZwkMUkjczXeaOD1htFJ
TL9e2RKsrWBVFIaiG1JgFk2Jyd928=
復?化結果:
Hello, world!!
BASE64:
SGVsbG8sIHdvcmxkZmc=

 


--------------------------------------------------------------------------------
openssl_open(), openssl_seal()의 예:
…각각의 공개키를 가진 복수의 사용자에 대해서 같은 데이터를 암호화하여 보내는 경우에 사용한다.
 
- 송신측(송신처1의 공개키 user1_public.pem 과 송신처2의 공개키 user2_public.pem 를 가지고 있는 것으로 한다. 자신의 키는 필요없다.)

 

// 보낼 곳의 공개키 일람
    $pubkeys = array(
        file_get_contents("user1_public.pem"),
        file_get_contents("user2_public.pem"),
    );
 
// 보낼 내용
    $real_message = "Hello, world!!";
 
// 암호화데이터의 결과저장변수
    $encrypted = "";

// 복호화에 필요한 エンベロ?プ키(?) $pubkeys 의 수만큼만 저장된다.
    $ekeys = array();
 
    if(!openssl_seal($real_message, $encrypted, $ekeys, $pubkeys)){
        echo "暗?化に失敗しましたn";
        die;
    }
 
// 출력. エンベロ?プ키와 암호화데이터에 관해서는 바이트코드라서, 표시를 위해 BASE64 엔코딩합니다.
    for($i = 0; $i < count($pubkeys); $i++){
        echo "送り先番?: $in" .
             "使った公開鍵: n" .
             $pubkeys[$i] ."n" .
             "??するエンベロ?プキ?: n" .
             base64_encode($ekeys[$i]) ."n" .
             "暗?化されたデ?タ: n" .
             base64_decode($encrypted);
    }


// 수신측(송신측으로부터 エンベロ?プ키 $ekey 와 암호화데이터 $encrypted 를 받도록 한다.)


// 송신측이 암호화에 사용한 공개키(user1_public.pem)에 대응하는 비밀키
    $private_key = file_get_contents("user1_private.pem");
 
// 결과저장변수. 복호화한 문자열이 들어간다.
    $message = "";
 
    if(!openssl_open($encrypted, $message, $ekey, $private_key)){
        echo "復?化に失敗しましたn";
        die;
    }
 
// 결과표시
    echo $message . "n";

 


송신측 결과는 다음과 같이 된다.

--------------------------------------------------------------------------------

送り先番?: 0
使った公開鍵:

--------------------------------------------------------------------------------
-BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzZFcKoXbuWzGvlv++7Y05/jBh
nYC+PM67v3H2I5pYV8tUz/6GqsG5afFgLJYoWPEd3KYXHb46B0GxEOydOTuTLEcv
+gVr6v4khgOgjxOcM1hlv+EvAThm1lIY1Y5lbTv+MEUyrGm7SDk8iUaHF6OBcQp3
NzkO6j3+YrsC8znXPwIDAQAB

--------------------------------------------------------------------------------
-END PUBLIC KEY-----
??するエンベロ?プキ?:
lu4ON1xW2hrrS1jXfav6mjWD32+Iuz1Jk20vhDRmSsfEp3vXuij7Z0R/ClhpgE9MxDJADiU
LS/CCUPuiZ3wUDErccfUFGGgcBKFsoXOgcX/vSfhi8yCYu3BOD+h5fOMmg/ZVe6NMjCVq50
D8yce5gPoypg2LHijse+0R1bPil8o=
暗?化されたデ?タ:
0qf1eWjjaHkiqRFKijam

--------------------------------------------------------------------------------

送り先番?: 1
使った公開鍵:

--------------------------------------------------------------------------------
-BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzZFcKoXbuWzGvlv++7Y05/jBh
nYC+PM67v3H2I5pYV8tUz/6GqsG5afFgLJYoWPEd3KYXHb46B0GxEOydOTuTLEcv
+gVr6v4khgOgjxOcM1hlv+EvAThm1lIY1Y5lbTv+MEUyrGm7SDk8iUaHF6OBcQp3
NzkO6j3+YrsC8znXPwIDAQAB

--------------------------------------------------------------------------------
-END PUBLIC KEY-----
??するエンベロ?プキ?:
Hpv4sE4M4RGnbEAPMqFKxOOPDJG0hpWBoIXCe8xUaIzx/dskUQ/a+T4jYyw+RRGh11wlzZt
CJOjzkP3pbafc0ymElAzS8RFAne7bVuCJh44UF55thAUo0nZVo1/2Wz9HuTDL23AYwc+jyh
U/k24bpGh81VJl5I7IkItoDeiS70Y=
暗?化されたデ?タ:
0qf1eWjjaHkiqRFKijam


수신측 결과:


Hello, world!!


참고:
- OpenSSL ??(php.net)
 PHP マニュアルの OpenSSL ??についての項目。
- OpenSSL 公式サイトの日本語?サイト
更新は不定期のようですが、openssl のマニュアルが?考になります。
公式はこちらです。

 

 

 

<원문>

PHP で OpenSSL 関数を使ってみたので、定番のハローワールドを置いておきます。

 


OpenSSL 関数で暗号化、復号化を行うには、
暗号化、復号化に必要な鍵のペアを PEM 形式で生成する必要があります。
1. パスワード付き秘密鍵 private_password.pem を生成

 

$ openssl genrsa private_password.pem -des3 1024

2. (1)からパスワードのない秘密鍵 private.pem を生成

$ openssl rsa -in private_password.pem -out private.pem

3. (1)を削除

$ rm private_password.pem

4. (2)から公開鍵 public.pem を生成

$ openssl rsa -in private.pem -pubout -out public.pem

 


openssl_public_encrypt(), openssl_private
…公開鍵で暗号化し、秘密鍵で復号化します。
つまり、誰からでも暗号化して送れるが、内容を読めるのは秘密鍵を持っている人だけになるため、通信経路での傍受が不可能になり、内容が外部に洩れる心配がないので機密性が高くなります。
ただし誰でも暗号化できるので全く別の内容へのかいざんは可能であり、必ずしも信頼性はありません。
 

 

// 暗号化に使う公開鍵
$public_key = file_get_contents(“public.pem”);
 
// 暗号化する文字列
$message = “Hello, world!!”;
 
// 暗号化データの結果格納先
$encrypted = “”;
 
// 暗号化実行
if(!openssl_public_encrypt($message, $encrypted, $public_key)){
    echo “暗号化に失敗\n”;
    die;
}
 
// 暗号化結果を表示(そのままでは表示できないのでBASE64エンコードする)
echo “暗号化データ: \n “.base64_encode($encrypted) . “\n”;
 
$message = null;
// ———————
// 復号化
// ———————
// 暗号化に使った公開鍵に対応する秘密鍵
$private_key = file_get_contents(“private.pem”);
 
// 復号化結果格納先
$result = “”;
 
// 復号化実行
if(!openssl_private_decrypt($encrypted, $result, $private_key)){
    echo “復号化に失敗\n”;
    die;
}
 
// 結果出力
echo “復号化結果: \n ” . $result . “\n”
     “BASE64:\n” . base64_encode($result).”\n”; // 比較用

結果:

暗号化データ:
FmPaJ9jOmjl/mK249NqUPzYjPUHsmFkSuNyp0SMlgW1c9RRzmKXBjcRhXH/5fwTxItAcE8/
AlZkjYo27XvGR7a3hdXxgaXbk4VORdRRk8LJXKB+xlVzF48OlHJ5lKUrXUdfr2BFtx53/IH
431mBlYWDhf+KyW608eKAA0T34qRY=
復号化結果:
Hello, world!!
BASE64:
SGVsbG8sIHdvcmxkZmc=

 


openssl_private_encrypt(), openssl_public_decrypt() の例:
…秘密鍵で暗号化し、公開鍵で復号化します。
つまり、鍵の所有者しか暗号化できないので中身のかいざんも、経路での差し替えも不可能になり、内容についての信頼性が高くなります。
ただし誰でも読めるため、内容の機密性はありません。
 
秘密鍵、公開鍵の使い方を逆にする以外は上の例と全く同じです。

 

// 暗号化に使う秘密鍵
$private_key = file_get_contents(“private.pem”);
 
// 暗号化する文字列
$message = “Hello, world!!”;
 
// 暗号化データの結果格納先
$encrypted = “”;
 
// 暗号化実行
if(!openssl_private_encrypt($message, $encrypted, $private_key)){
    echo “暗号化に失敗\n”;
    die;
}
 
// 暗号化結果を表示(そのままでは表示できないのでBASE64エンコードする)
echo “暗号化データ: \n “.base64_encode($encrypted) . “\n”;
 
$message = null;
// ———————
// 復号化
// ———————
// 暗号化に使った秘密鍵から作られた公開鍵
$public_key = file_get_contents(“public.pem”);
 
// 復号化結果格納先
$result = “”;
 
// 復号化実行
if(!openssl_public_decrypt($encrypted, $result, $public_key)){
    echo “復号化に失敗\n”;
    die;
}
 
// 結果出力
echo “復号化結果: \n ” . $result . “\n”
     “BASE64:\n” . base64_encode($result).”\n”; // 比較用

結果:

暗号化データ:
CII4EW6LQBq0faVJxshUfk9VCdFsE66DnQPVdsLbvfq7tNCMzAIZbZA3GBxHu4cG2TqvOnn
xN9C9S9IgBIbulfj4c90IkrYtHQGt3RHAJBYiAgfmzCKbMr2cPJhZwkMUkjczXeaOD1htFJ
TL9e2RKsrWBVFIaiG1JgFk2Jyd928=
復号化結果:
Hello, world!!
BASE64:
SGVsbG8sIHdvcmxkZmc=

 


openssl_open(), openssl_seal() の例:
…同報メールのように、別々の公開鍵を持つ複数の相手に対して同じデータを暗号化して送る場合に使います
 
– 送信側(送信先1の公開鍵 user1_public.pem と送信先2の公開鍵 user2_public.pem を持っているとする. 自分の鍵は必要としない)

 

// 送り先の公開鍵一覧。
$pubkeys = array(
        file_get_contents(“user1_public.pem”),
        file_get_contents(“user2_public.pem”),
   );
 
// 送る内容
$real_message = “Hello, world!!”;
 
// 暗号化データの結果格納先
$encrypted = “”;
// 復号化に必要なエンベロープキーの格納先。$pubkeys の数だけ格納される。
$ekeys = array();
 
if(!openssl_seal($real_message, $encrypted, $ekeys, $pubkeys)){
    echo “暗号化に失敗しました\n”; 
    die;
}
 
// 出力. エンベロープキーと暗号化データについてはバイトコードなので、表示のために BASE64 エンコードしています。
for($i = 0; $i < count($pubkeys); $i++){
    echo “送り先番号: $i\n” .
         “使った公開鍵: \n” . 
         $pubkeys[$i] .”\n” .
         “対応するエンベロープキー: \n” . 
         base64_encode($ekeys[$i]) .”\n” .
         “暗号化されたデータ: \n” . 
         base64_decode($encrypted);
}

 
受信側(送信側からエンベロープキー $ekey と暗号化データ $encrypted を受け取っているとする):

// 送信側が暗号化に使った公開鍵(user1_public.pem)に対応する秘密鍵
$private_key = file_get_contents(“user1_private.pem”);
 
// 結果格納先。復号化した文字列が入る
$message = “”;
 
if(!openssl_open($encrypted, $message, $ekey, $private_key)){
    echo “復号化に失敗しました\n”;
    die;
}
 
// 結果表示
echo $message . “\n”;

 
送信側結果は次のようになります。


送り先番号: 0
使った公開鍵:

 


-BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzZFcKoXbuWzGvlv++7Y05/jBh
nYC+PM67v3H2I5pYV8tUz/6GqsG5afFgLJYoWPEd3KYXHb46B0GxEOydOTuTLEcv
+gVr6v4khgOgjxOcM1hlv+EvAThm1lIY1Y5lbTv+MEUyrGm7SDk8iUaHF6OBcQp3
NzkO6j3+YrsC8znXPwIDAQAB

 


-END PUBLIC KEY—–
対応するエンベロープキー: 
lu4ON1xW2hrrS1jXfav6mjWD32+Iuz1Jk20vhDRmSsfEp3vXuij7Z0R/ClhpgE9MxDJADiU
LS/CCUPuiZ3wUDErccfUFGGgcBKFsoXOgcX/vSfhi8yCYu3BOD+h5fOMmg/ZVe6NMjCVq50
D8yce5gPoypg2LHijse+0R1bPil8o=
暗号化されたデータ: 
0qf1eWjjaHkiqRFKijam

 


送り先番号: 1
使った公開鍵:

 


-BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzZFcKoXbuWzGvlv++7Y05/jBh
nYC+PM67v3H2I5pYV8tUz/6GqsG5afFgLJYoWPEd3KYXHb46B0GxEOydOTuTLEcv
+gVr6v4khgOgjxOcM1hlv+EvAThm1lIY1Y5lbTv+MEUyrGm7SDk8iUaHF6OBcQp3
NzkO6j3+YrsC8znXPwIDAQAB

 


-END PUBLIC KEY—–
対応するエンベロープキー:
Hpv4sE4M4RGnbEAPMqFKxOOPDJG0hpWBoIXCe8xUaIzx/dskUQ/a+T4jYyw+RRGh11wlzZt
CJOjzkP3pbafc0ymElAzS8RFAne7bVuCJh44UF55thAUo0nZVo1/2Wz9HuTDL23AYwc+jyh
U/k24bpGh81VJl5I7IkItoDeiS70Y=
暗号化されたデータ:
0qf1eWjjaHkiqRFKijam

 

受信側結果:

Hello, world!!

 

STT Tiêu đề sitelink1 Người gửi Ngày gửi Đã xem
Chú ý [계속 추가중] SBOM 용어 정의   황제낙엽 2025.04.10 121
Chú ý [계속 추가중] Keycloak 용어 및 설정 옵션 정의   황제낙엽 2024.02.02 674
28 파일 해쉬 알고리즘 CRC   황제낙엽 2009.12.01 416
27 해쉬 알고리즘의 종류   황제낙엽 2009.12.01 409
26 Ajax 보안 관련 문서 (Attacking AJAX Web Applications) file   황제낙엽 2009.02.12 177
25 blowfish 알고리즘 file http://www.schneier.com/blowfish.html  황제낙엽 2008.01.22 246
24 OpenSSL을 이용한 보안 통신 API의 설계 및 구현 file   황제낙엽 2007.10.01 199
23 Windows환경에서의 OpenSSL설치 file   황제낙엽 2007.09.28 155
22 OpenSSL Command-Line HOWTO   황제낙엽 2007.09.27 928
21 Certificate Server의 설치 와 Client인증 http://wiki.kldp.org/wiki.php/LinuxdocSgml/OpenSSL-KLDP  황제낙엽 2007.09.27 313
20 OpenSSL의 설치 및 운영 http://user.chol.com/~laday/solaris/openssl.html  황제낙엽 2007.09.27 201
19 OpenSSL 프로그래밍   황제낙엽 2007.09.27 1372
18 OpenSSL 을 통한 파일 암호화   황제낙엽 2007.09.27 370
17 OpenSSL 과 OpenSSH 소스 파일 (Language : C)   황제낙엽 2007.09.24 184
16 RSA 암호화 알고리즘을 구현한 C++ 예제 file   황제낙엽 2007.09.17 1405
15 RSA암호화를 이용한 로그인 ID/패스워드 정보 관리 http://blog.dalsu.net/61  황제낙엽 2007.09.05 262
» PHP와 OpenSSL http://www.ecoop.net/memo/2007-04-26-3.html  황제낙엽 2007.09.27 283
13 RSA 공개키 암호화 알고리즘 - PHP 구현[2] file   황제낙엽 2007.09.27 413
12 RSA 공개키 암호화 알고리즘 - PHP 구현[1] file   황제낙엽 2007.09.05 181
11 OpenSSL사용방법 메모, RSA암호의 최대 사이즈, JCA/JCE가이드   황제낙엽 2007.09.27 174
10 Java Cryptography Extension (JCE) 개요   황제낙엽 2007.09.27 409
9 Java에서 암호화하고 C++에서 복호화하는 방법   황제낙엽 2007.09.27 380