Private key, Public key

Zeung-il Kim
9 min readMar 22, 2019

PKI 시스템에서 개인키, 공개키, 인증서(그 안에 공개키) 등을 서로 추출해보는 과정을 살펴보자.

개인키를 만들면 1:1 대응이 되는 공개키를 추출할 수 있다.

개인키로 CSR을 만들고 CSR과 개인키를 이용해서 인증서를 만든다. Self-signed라면 CSR을 만들때 사용되는 개인키와 인증서를 만들때 사용되는 개인키는 동일하다. 하위 인증서를 만드는 경우라면 CSR은 자신의 개인키(하위 인증서의 개인키)로 만들고, 인증서 생성 시 사용되는 개인키는 상위 CA의 개인키가 사용된다.

만들어진 인증서에는 자신의 개인키에 해당하는 공개키 값이 들어가게 된다. 즉, 인증서에서 공개키를 추출할 수 있고 이는 해당 개인키로 부터 추출한 값과 같다.

개인키를 생성한다.
openssl ecparam -genkey -name prime256v1 -noout -out my_priv_key.pem
cat my_priv_key.pem 로 내용을 보면 Elliptic Curve 형식의 개인키가 생성됨을 알 수 있다.
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIF93XJuuqlLZ5+zGoiJB2VGucuSB50HKIVUx9oozUauIoAoGCCqGSM49
AwEHoUQDQgAEBjyhntijd9NXWzc6zozIZL5/BG9V1jCKS/87oeWjbapSMy67k4l5
CM/Fbp+f0WYdK7ke0faPTeapSMogiIYWew==
-----END EC PRIVATE KEY-----
암호화된 개인키를 생성하려면
openssl ecparam -genkey -name prime256v1 | openssl ec -aes-128-cbc -out encrypted_my_priv_key.pem
cat encrypted_my_priv_key.pem 로 내용을 보면 encrypted 되었다는 정보를 알 수 있다.
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,DE580C49672271463606CAF0A28E4639
e6XlsCOSw7F5ht0b8yLeLTeGr/edYd7Y5XkAfc6DkjZ6u0cVQAtsiH4/yV6k4GJq
AI4ajQt9Wg+OF6H3UXRAROKdXE01fNFv3UBz6F87rDABPxs0HPiUPQWPsTmmGm6g
bG+RKD+rUO345+1ujwL3y8kvyO+IVA34rV2ort5nw2k=
생성된 내 개인키를 이용해서 인증서를 만들어 보자. 먼저 csr(cert.signing request)을 만든다.
openssl req -new -key my_priv_key.pem -out my_cert.csr
생성된 csr검증 및 내용 보기
openssl req -text -noout -verify -in my_cert.csr
생성된 csr을 이용해서 x.509 인증서를 생성한다.(self-signed)
openssl x509 -req -in my_cert.csr -signkey my_priv_key.pem -sha256 -set_serial 5106956 -out my_cert.pem -days 3650
인증서 정보 살펴보기
openssl x509 -in my_cert.pem -text -noout
생성된 인증서에서 공개키를 뽑아 보자.
openssl x509 -pubkey -in my_cert.pem > my_pub_key.pem
cat my_pub_key.pem으로 값을 확인 해 보면
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBjyhntijd9NXWzc6zozIZL5/BG9V
1jCKS/87oeWjbapSMy67k4l5CM/Fbp+f0WYdK7ke0faPTeapSMogiIYWew==
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
MIIBQDCB6AIDTe0MMAoGCCqGSM49BAMCMCwxCzAJBgNVBAYTAktSMRAwDgYDVQQK
DAdIeXVuZGFpMQswCQYDVQQDDAJNWTAeFw0xOTAzMjEyMjUxMjBaFw0yOTAzMTgy
MjUxMjBaMCwxCzAJBgNVBAYTAktSMRAwDgYDVQQKDAdIeXVuZGFpMQswCQYDVQQD
DAJNWTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAY8oZ7Yo3fTV1s3Os6MyGS+
fwRvVdYwikv/O6Hlo22qUjMuu5OJeQjPxW6fn9FmHSu5HtH2j03mqUjKIIiGFnsw
CgYIKoZIzj0EAwIDRwAwRAIgM07wQeYroEMWOB5jHRd/X1XioeIT03AFp5Pn3zvl
qGQCIFrS+tRe7x46AXWqXhe2ACxTks3NyxMAtq5QFVsUtRzN
-----END CERTIFICATE-----
개인키에서 바로 공개키를 뽑아 보자.
openssl ec -in my_priv_key.pem -pubout -out my_pub_key2.pem
cat my_pub_key2.pem
으로 값을 확인 해 보면
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBjyhntijd9NXWzc6zozIZL5/BG9V
1jCKS/87oeWjbapSMy67k4l5CM/Fbp+f0WYdK7ke0faPTeapSMogiIYWew==
-----END PUBLIC KEY-----
my_pub_key.pem과 my_pub_key2.pem 두 개 값을 보면 같은 것을 알 수 있다.?? 인증서을 열어서 보이는 Public key hex값 하고는 어떻게 매칭 되는지 모르겠다.

인증서 체인을 만들어 보자.

위에서 만든 my_cert.pem을 상위 인증서라고 가정하고, 그 하위 인증서로 sub_my_cert.pem을 만들어 보자.먼저 하위 인증서의 개인키를 생성한다.
openssl ecparam -genkey -name prime256v1 -noout -out my_sub_priv_key.pem
csr을 만들자openssl req -new -key my_sub_priv_key.pem -out my_sub_cert.csrcsr을 이용해서 인증서를 만든다.
openssl x509 -req -in my_sub_cert.csr -CA my_cert.pem -CAkey my_priv_key.pem -set_serial 1 -out my_sub_cert.pem -days 365
생성된 인증서에서 공개키를 뽑아 보자.
openssl x509 -pubkey -in my_sub_cert.pem > my_sub_pub_key.pem
하위 인증서 개인키에서 바로 공개키를 뽑아 보자.
openssl ec -in my_sub_priv_key.pem -pubout -out my_sub_pub_key2.pem
두 공개키를 비교 해보면 당연히 똑같다.

서명 검증 하기

인증서 검증 목적은 보낸 파일이 무결성을 확인 하는데 목적이 있다. 송신측에서는 보내고자 하는 파일(cantools.pdf)의 서명값을 만든다. (hash를 뜬 다음 서명함.) 자신의 개인키로 서명함.openssl dgst -sha256 -sign my_priv_key.pem cantools.pdf > cantools_signature.bincantools.pdf와 서명값 cantools_signature.bin을 같이 보내 주면
수신 측에서는 상대방의 공개키를 가지고 서명값을 검증함으로써 데이터 무결성을 확인 한다.
openssl dgst -sha256 -verify my_pub_key.pem -signature cantools_signature.bin cantools.pdf
Verified OK

데이터 암호화/복호화

ECC에서는 바로 데이터를 암호화 하거나 복호화 하지 않고 DH(Diffie-Hellman) Key exchange 방식을 사용해서 shard secret을 만들고 이를 이용해서 암호화 통신을 한다. 
이것을 ECDH (ECC + DH)라고 함.
자신의 개인키와 상대방의 공개키를 활용해서 shared secret을 만들어 보자.openssl pkeyutl -derive -inkey kim_priv_key.pem -peerkey park_pub_key.pem -out kim_shared_secret.binopenssl pkeyutl -derive -inkey park_priv_key.pem -peerkey kim_pub_key.pem -out park_shared_secret.binbase64 kim_shared_secret.bin
base64 park_shard_secret.bin 이 두값을 보면 똑같다는 것을 알 수 있음.
이제 이 정보를 이용해서 대칭키암호화 통신을 할 수 있다. 예를 들면echo 'Hello crypto world!' > plain.txt
openssl enc -aes256 -base64 -k $(base64 kim_shared_secret.bin) -e -in plain.txt -out cipher.txt
openssl end -aes256 -base64 -k $(base64 park_shared_secret.bin) -d -in cipher.txt -out plain_again.txt

--

--