Search

understand-tls-certificate-with-hand-on-practice-1

작년에 회사에서 SSL/TLS 인증서 갱신 작업을 했다. 회사가 합병과 이사를 해서 정보가 바뀌어 CSR 생성부터 모든 과정을 했다. 당시엔 연마다 반복해야하는 작업이니 절차를 매뉴얼화 했다. 실제로 권한이 있고 명령어 복붙하면 비개발자 또는 웹 통신과 보안에 이해가 전혀 없는 사람도 할 수 있을 정도로 만들었다.
올해 다시 인증서 갱신하려 보니 내가 그런 사람인거 같았다. 실제로 인증서의 암호화나 인증 과정을 정확히 몰랐다. 따라서 SSL/TLS 인증과 관련한 키워드 검색해서 공부했다. 하지만 내가 단번에 이해할 수 있는 글은 없었다(물론 크게 도움이 된 글도 있다). 너무 추상화된 설명 또는 실제 인증서나 키를 예제로 사용해서 생략되는 부분도 많았다.
이 부분에 끄덕였다면 인증서에 대해 잘 모르고 있다는 반증이다. 인증서는 노출되어도 아무 문제가 없다. 인증서는 누구나 볼 수 있다(노출하면 안되는 것은 키 중에서도 ’비밀키’이다).
여러 글들을 읽어가며 나는 실제 TLS 인증서를 흉내내어 로컬에 하고 테스트 해볼 수 있었다(마참내!). 물론 그 중에선 더 이상 자세히 들여다 볼 수 없는 부분도 있었다. 하지만 SSL/TLS 인증서가 어떻게 동작하는지 전보다 명확히 이해 되어 글로 정리한다.
이 글을 이런 사람이 읽으면 좋다(aka 나 같은 사람): - SSL/TLS 인증서를 발급, 갱신 해봤지만 정확히 ’인증’이 어떻게 동작하는지 모른다. - RSA, PKI, SHA256 등 암호 관련 약어, 키워드는 많이 들어봤지만 정확히 어떤 뜻인지 모른다. - 공개키, 개인키, 대칭/비대칭키 등의 암호학 개념이 추상적인 그림으로만 있고 실제 파일에 쓰인 값과 매칭이 안되는 사람. - 그리고 나 같은 사람 말고 암호학, 웹 보안 고수가 이 글을 읽고 지적해주시면 고맙겠습니다.
이 글은, 내가 궁금했고 이를 해소한 과정을 재구성하여, 다음 순서로 진행된다: 1. 실제 인증서를 보고 궁금한 점을 찾아 본다. 2. 인증서를 발급하고 인증되는 과정을 최대한 실제와 가깝게 실습한다(Self-signed certificate). 3. 나머지 생략한 개념들을 키워드 별로 정리한다.

인증서를 보자

우리 회사 인증서를 예로 들겠다. 크롬 주소창에 cre.ma를 입력해 접속하고 주소창 왼쪽 자물쇠 표시를 눌러 인증서를 확인하자:
‘이 사이트는 보안 연결(HTTPS)이 사용되었습니다.’ -> ‘인증서가 유효함’ 순서대로 클릭하면 크롬 중앙 모달에 인증서가 뜬다. 세부사항 신뢰 등을 누르면 인증서가 어떻게 생겼는지 알 수 있다.
여기서 첫번째 궁금증은 “내가 갱신해서 받았던 인증서는 이렇게 안생겼는데”였다. MII…로 시작하는 해시 값 덩어리였다. 세부사항을 눌러서 보이는 제목 이름 이란 섹션은 CSR 생성 시 회사 정보를 입력했던 기억이 있지만 나머지는 뭐지?
두번째 궁금증은 “인증서가 여러개네?”였다. 인증 업체인 DigiCert에 인증서를 요청하고 받아 쓰긴 한다. DigiCert Global Root CA -> DiCert TLS RSA SHA256 2020 CA1 -> 발급 받은 인증서의 3단계로 각각 인증서가 있는걸로 보인다. 인증 업체 이름 인증서들의 역할은 뭘까?

더 자세히 보자

터미널에서 openssl을 사용하여 인증서를 확인해보자. openssl은 해시 함수 암/복호화나 인증서 생성 등 SSL 관한 모든 동작을 할 수 있다. 로컬 맥북에서 했고 homebrew를 통해 최신인 3버전을 설치했다(brew install openssl@3). PATH 앞에 설치한 openssl@3의 bin 경로를 추가하자:
❯ openssl versionOpenSSL 3.0.1 14 Dec 2021 (Library: OpenSSL 3.0.1 14 Dec 2021)❯ openssl s_client -connect cre.ma:443 < /dev/nullCONNECTED(00000005)depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CAverify return:1depth=1 C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1verify return:1depth=0 C = KR, ST = Seoul, L = Seongdong-gu, O = CREMA Inc., CN = *.cre.maverify return:1---Certificate chain 0 s:C = KR, ST = Seoul, L = Seongdong-gu, O = CREMA Inc., CN = *.cre.ma i:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1 a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Jan 21 00:00:00 2021 GMT; NotAfter: Feb 20 23:59:59 2022 GMT 1 s:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1 i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Sep 24 00:00:00 2020 GMT; NotAfter: Sep 23 23:59:59 2030 GMT---Server certificate-----BEGIN CERTIFICATE-----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-----END CERTIFICATE-----subject=C = KR, ST = Seoul, L = Seongdong-gu, O = CREMA Inc., CN = *.cre.maissuer=C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1---No client certificate CA names sentPeer signing digest: SHA256Peer signature type: RSA-PSSServer Temp Key: X25519, 253 bits---SSL handshake has read 3508 bytes and written 405 bytesVerification: OK---New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384Server public key is 2048 bitSecure Renegotiation IS supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 3BB10824D86FEADBB2170BB2B728BE31A37A4710E45911E291B200EF2B9F0175 Session-ID-ctx: Master-Key: 1F4C2B8BDCFAC20C2BF10E65A91F5930EA5DEC664F044E9BEA892B97AE44457FFD856E418C6DFFC3BD96B709ED112707 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 600 (seconds) TLS session ticket: 0000 - b4 2c 8f 0d b9 ca 25 51-49 24 48 ba 4c 97 56 63 .,....%QI$H.L.Vc 0010 - 35 9c e6 49 0d c3 9d 9b-cc 8f a9 dd fe 21 d9 2d 5..I.........!.- 0020 - a1 c7 d8 5f 36 01 f7 dd-ba 6b e9 41 a8 6a 52 6d ..._6....k.A.jRm 0030 - 4e 2b 14 f3 51 c3 e9 f9-04 5c 6d f2 23 52 33 2d N+..Q....\m.#R3- 0040 - 7e 4a f7 36 7e b6 65 4d-b5 23 59 b6 ac 77 00 5a ~J.6~.eM.#Y..w.Z 0050 - ab d4 92 b7 05 a7 93 62-ec c1 b8 c6 be 02 0f 3c .......b.......< 0060 - c1 72 f9 5c e8 f3 67 1e-74 88 7e 05 ea 5d 53 d9 .r.\..g.t.~..]S. 0070 - 20 4a 4f f9 1b ab 87 0a-9c f4 aa 65 87 01 b1 70 JO........e...p 0080 - e5 1f 6e 77 03 ac 8f 6e-c7 ee d6 39 4d 7b 97 59 ..nw...n...9M{.Y 0090 - 5a f6 49 22 dc 60 c4 0f-6f e7 47 96 a5 7e e0 54 Z.I".`..o.G..~.T 00a0 - 44 2b e1 fc 0e 10 22 d1-01 6e d6 fe d6 96 f4 78 D+...."..n.....x 00b0 - 19 2a f9 ce be 93 08 45-d4 b0 4b 6e 1b 1b 1a 65 .*.....E..Kn...e Start Time: 1642045212 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: yes---DONE
Shell
복사
s_client: connect 옵션으로 목적지 포트에 TLS 연결을 한다.
< /dev/null: SSL 연결 후 메세지 입력을 기다리는데 우린 인증서만 필요하기 때문에 연결만 했다.
이 명령은 브라우저에서 화면 렌더하는 부분 직전까지와 같다. 즉 SSL 연결까지 한다. 명령 결과에서 얻을 수 있는 정보가 더 많아 보인다. 각 부분을 살펴 보면:
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CAverify return:1depth=1 C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1verify return:1depth=0 C = KR, ST = Seoul, L = Seongdong-gu, O = CREMA Inc., CN = *.cre.maverify return:1
Shell
복사
1.
먼저 depth가 2,1,0 내림차순으로 있다. CommonName(CN)을 보면 브라우저에서 본 인증서와 같이 DigiCert 인증서들이 있고 내가 설치한 회사 인증서(편의상 앞으로 subject라고 함)가 있다.
Certificate chain 0 s:C = KR, ST = Seoul, L = Seongdong-gu, O = CREMA Inc., CN = *.cre.ma i:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1 a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Jan 21 00:00:00 2021 GMT; NotAfter: Feb 20 23:59:59 2022 GMT 1 s:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1 i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Sep 24 00:00:00 2020 GMT; NotAfter: Sep 23 23:59:59 2030 GMT
Shell
복사
1.
Certificate Chain이란 부분이다. 위의 세 인증서 사이를 이어주는 고리이다:
s: subject(DN)
i: issuer(발급자 DN)
a: algorithm?
v: Verification Dates 이다. subject는 “DigiCert TLS RSA SHA256 2020 CA1”가, 또 그 인증서는 “DigiCert Global Root CA”가 인증해준 것이다.
Server certificate -----BEGIN CERTIFICATE----- MIIGKjCCBRKgAwIBAgIQA8E00cotfeJu6tyUUdcRFDANBgkqhkiG9w0BAQsFADBP MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSkwJwYDVQQDEyBE aWdpQ2VydCBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTAeFw0yMTAxMjEwMDAwMDBa Fw0yMjAyMjAyMzU5NTlaMFwxCzAJBgNVBAYTAktSMQ4wDAYDVQQIEwVTZW91bDEV MBMGA1UEBxMMU2Vvbmdkb25nLWd1MRMwEQYDVQQKEwpDUkVNQSBJbmMuMREwDwYD VQQDDAgqLmNyZS5tYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMoZ maCa7F+E0lrzC+qV3VxQQRIGqfdVTcCcFxdyJjHuYxeKgiy3lGv/vCWLlQrJM+bJ 3ZI9t3P+ZOO7aZ1PzbRx3FWTP3CFW+22uXpPY5qv1EM3H9fV/FBELp/ScBdf5jcz /5skFZx7vEGNm9XVNTdtxJe3csVJTf8dOHgcyPb/ikihtgN99CIMZ5Dik0bnFNhH S+O7S0V8kLNURvRLPb/QKX4kp89BzTaUELBMZQHwlbwGlcCfhx4cXXNmHIWt8nCh sMT11gKttM1nLhQId3p2doURTn6okutmheEFFKUhO7ep9OG4a/Dppd4e/AWw8Dhg U1o5jnN5FFlU7DfcIpcCAwEAAaOCAvMwggLvMB8GA1UdIwQYMBaAFLdrouqoqoSM eeq02g+YssWVdrn0MB0GA1UdDgQWBBRy9XXSRR3z1uzoF4Xn4tnKTycQ4DAbBgNV HREEFDASgggqLmNyZS5tYYIGY3JlLm1hMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwgYsGA1UdHwSBgzCBgDA+oDygOoY4aHR0 cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExTUlNBU0hBMjU2MjAyMENB MS5jcmwwPqA8oDqGOGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRM U1JTQVNIQTI1NjIwMjBDQTEuY3JsMD4GA1UdIAQ3MDUwMwYGZ4EMAQICMCkwJwYI KwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzB9BggrBgEFBQcB AQRxMG8wJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBHBggr BgEFBQcwAoY7aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExT UlNBU0hBMjU2MjAyMENBMS5jcnQwDAYDVR0TAQH/BAIwADCCAQQGCisGAQQB1nkC BAIEgfUEgfIA8AB2ACl5vvCeOTkh8FZzn2Old+W+V32cYAr4+U1dJlwlXceEAAAB dyJlOdcAAAQDAEcwRQIhAKWWY4duHzlJlXL3O9C4hU9EjhRcmDHBnAMdlyWudMeu AiAA0ueN1JP/tDVhzJJ96gjhU8JhoVLTc5qPxPycQwBrzgB2ACJFRQdZVSRWlj+h L/H3bYbgIyZjrcBLf13Gg1xu4g8CAAABdyJlOiYAAAQDAEcwRQIhAJ5E73JvM8Y7 HU1veJ7PlWbbxrdtw2z9w9xU+7/NAlNuAiAZ2+PGAAdrLjDMnL1CaBlII8kbRYdn 2U4W8bEp5xeWkDANBgkqhkiG9w0BAQsFAAOCAQEArXuG/kKbof6qvgd/CmMf8o3i 61dHzjdO09Vmw73K9wFiggLb3Dt6cxPLfplI9I+2+3K9xkuyiNSghClmiE8+AZsR pucRi1hZYrckj52AcSZ9WXzaBssMMDtXipmg912sz3cjBqcEhZwbxka5I8ih0PAP VEXzsZJTbokVD1Nb4SfJuDqgiBARmLiwHi7/b+RGtfHkGsiIYID6VCXPDvWgja4/ qBdZtYG+Qw0K8Iqu0x0pGewq4t6RuyMaTOBj5DvhIuQTqNFWxj5iuTlZpkPUrg9B KJyRw0fr/aKxqYHbXPc7VAV22k2sok2ihd9uX5JphzCM47b/XhVo6SX7PQ7DRg== -----END CERTIFICATE----- subject=C = KR, ST = Seoul, L = Seongdong-gu, O = CREMA Inc., CN = *.cre.ma issuer=C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
Plain Text
복사
1.
앞서 말한 해시 값인 인증서 파일이다. subject, issuer의 DN이 한번 더 쓰여 있다.
No client certificate CA names sentPeer signing digest: SHA256Peer signature type: RSA-PSSServer Temp Key: X25519, 253 bits
Shell
복사
1.
TLS handshake 과정에서 클라이언트가 추가적인 CA names 목록을 주는 것에 대한 내용이다. 명령에서 이 옵션을 사용하지 않았고 글에서 handshake는 자세히 설명하지 않는다.
SSL handshake has read 3508 bytes and written 405 bytesVerification: OK
Shell
복사
1.
SSL handshake가 맺어졌다.
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384Server public key is 2048 bitSecure Renegotiation IS supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: 3BB10824D86FEADBB2170BB2B728BE31A37A4710E45911E291B200EF2B9F0175 Session-ID-ctx: Master-Key: 1F4C2B8BDCFAC20C2BF10E65A91F5930EA5DEC664F044E9BEA892B97AE44457FFD856E418C6DFFC3BD96B709ED112707 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 600 (seconds) TLS session ticket: 0000 - b4 2c 8f 0d b9 ca 25 51-49 24 48 ba 4c 97 56 63 .,....%QI$H.L.Vc 0010 - 35 9c e6 49 0d c3 9d 9b-cc 8f a9 dd fe 21 d9 2d 5..I.........!.- 0020 - a1 c7 d8 5f 36 01 f7 dd-ba 6b e9 41 a8 6a 52 6d ..._6....k.A.jRm 0030 - 4e 2b 14 f3 51 c3 e9 f9-04 5c 6d f2 23 52 33 2d N+..Q....\m.#R3- 0040 - 7e 4a f7 36 7e b6 65 4d-b5 23 59 b6 ac 77 00 5a ~J.6~.eM.#Y..w.Z 0050 - ab d4 92 b7 05 a7 93 62-ec c1 b8 c6 be 02 0f 3c .......b.......< 0060 - c1 72 f9 5c e8 f3 67 1e-74 88 7e 05 ea 5d 53 d9 .r.\..g.t.~..]S. 0070 - 20 4a 4f f9 1b ab 87 0a-9c f4 aa 65 87 01 b1 70 JO........e...p 0080 - e5 1f 6e 77 03 ac 8f 6e-c7 ee d6 39 4d 7b 97 59 ..nw...n...9M{.Y 0090 - 5a f6 49 22 dc 60 c4 0f-6f e7 47 96 a5 7e e0 54 Z.I".`..o.G..~.T 00a0 - 44 2b e1 fc 0e 10 22 d1-01 6e d6 fe d6 96 f4 78 D+...."..n.....x 00b0 - 19 2a f9 ce be 93 08 45-d4 b0 4b 6e 1b 1b 1a 65 .*.....E..Kn...e Start Time: 1642045212 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: yes---DONE
Shell
복사
1.
Handshake 후 맺어진 SSL session에 대한 내용이다. 연결마다 ID 같은 값들은 달라지게 된다. Verify return code를 보고 연결이, 즉 인증이 잘 된것만 확인하자.
Handshake 과정은 생략하고 Certificate chain이 무엇인지, 인증서는 어떤 정보를 담고 있는지 자세히 보자.

X509

Certificate chain은 브라우저 인증서에서도 볼 수 있었다.
openssl s_client 요청에선 인증서가 파일 그대로 왔고, 브라우저 인증서에선 세부 사항이라는 구조로 보였다.
먼저 후자에 대해서 알아보자. 명령 출력에서 보이는 포맷을 PEM이라고 한다. 인증서 파일 확장자도 .pem이다. PEM이 어떤 포맷인지는 나중에 설명한다. 하지만 눈으로 봤을 때 임의의 해시 값처럼 보여 이건 PEM이라고 알아볼 수 있다.
이 PEM으로 쓰인 인증서를 파일로 저장하고:
❯ openssl s_client -connect cre.ma:443 2>/dev/null </dev/null | gsed -n '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > cre_ma.pem❯ cat cre_ma.pem-----BEGIN CERTIFICATE-----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-----END CERTIFICATE-----
Shell
복사
다음 명령으로 파싱한다:
❯ openssl x509 -text -noout -in cre_ma.pemCertificate: Data: Version: 3 (0x2) Serial Number: 03:c1:34:d1:ca:2d:7d:e2:6e:ea:dc:94:51:d7:11:14 Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1 Validity Not Before: Jan 21 00:00:00 2021 GMT Not After : Feb 20 23:59:59 2022 GMT Subject: C = KR, ST = Seoul, L = Seongdong-gu, O = CREMA Inc., CN = *.cre.ma Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:ca:19:99:a0:9a:ec:5f:84:d2:5a:f3:0b:ea:95: dd:5c:50:41:12:06:a9:f7:55:4d:c0:9c:17:17:72: 26:31:ee:63:17:8a:82:2c:b7:94:6b:ff:bc:25:8b: 95:0a:c9:33:e6:c9:dd:92:3d:b7:73:fe:64:e3:bb: 69:9d:4f:cd:b4:71:dc:55:93:3f:70:85:5b:ed:b6: b9:7a:4f:63:9a:af:d4:43:37:1f:d7:d5:fc:50:44: 2e:9f:d2:70:17:5f:e6:37:33:ff:9b:24:15:9c:7b: bc:41:8d:9b:d5:d5:35:37:6d:c4:97:b7:72:c5:49: 4d:ff:1d:38:78:1c:c8:f6:ff:8a:48:a1:b6:03:7d: f4:22:0c:67:90:e2:93:46:e7:14:d8:47:4b:e3:bb: 4b:45:7c:90:b3:54:46:f4:4b:3d:bf:d0:29:7e:24: a7:cf:41:cd:36:94:10:b0:4c:65:01:f0:95:bc:06: 95:c0:9f:87:1e:1c:5d:73:66:1c:85:ad:f2:70:a1: b0:c4:f5:d6:02:ad:b4:cd:67:2e:14:08:77:7a:76: 76:85:11:4e:7e:a8:92:eb:66:85:e1:05:14:a5:21: 3b:b7:a9:f4:e1:b8:6b:f0:e9:a5:de:1e:fc:05:b0: f0:38:60:53:5a:39:8e:73:79:14:59:54:ec:37:dc: 22:97 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Authority Key Identifier: B7:6B:A2:EA:A8:AA:84:8C:79:EA:B4:DA:0F:98:B2:C5:95:76:B9:F4 X509v3 Subject Key Identifier: 72:F5:75:D2:45:1D:F3:D6:EC:E8:17:85:E7:E2:D9:CA:4F:27:10:E0 X509v3 Subject Alternative Name: DNS:*.cre.ma, DNS:cre.ma X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 CRL Distribution Points: Full Name: URI:http://crl3.digicert.com/DigiCertTLSRSASHA2562020CA1.crl Full Name: URI:http://crl4.digicert.com/DigiCertTLSRSASHA2562020CA1.crl X509v3 Certificate Policies: Policy: 2.23.140.1.2.2 CPS: http://www.digicert.com/CPS Authority Information Access: OCSP - URI:http://ocsp.digicert.com CA Issuers - URI:http://cacerts.digicert.com/DigiCertTLSRSASHA2562020CA1.crt X509v3 Basic Constraints: critical CA:FALSE CT Precertificate SCTs: Signed Certificate Timestamp: Version : v1 (0x0) Log ID : 29:79:BE:F0:9E:39:39:21:F0:56:73:9F:63:A5:77:E5: BE:57:7D:9C:60:0A:F8:F9:4D:5D:26:5C:25:5D:C7:84 Timestamp : Jan 21 00:43:15.287 2021 GMT Extensions: none Signature : ecdsa-with-SHA256 30:45:02:21:00:A5:96:63:87:6E:1F:39:49:95:72:F7: 3B:D0:B8:85:4F:44:8E:14:5C:98:31:C1:9C:03:1D:97: 25:AE:74:C7:AE:02:20:00:D2:E7:8D:D4:93:FF:B4:35: 61:CC:92:7D:EA:08:E1:53:C2:61:A1:52:D3:73:9A:8F: C4:FC:9C:43:00:6B:CE Signed Certificate Timestamp: Version : v1 (0x0) Log ID : 22:45:45:07:59:55:24:56:96:3F:A1:2F:F1:F7:6D:86: E0:23:26:63:AD:C0:4B:7F:5D:C6:83:5C:6E:E2:0F:02 Timestamp : Jan 21 00:43:15.366 2021 GMT Extensions: none Signature : ecdsa-with-SHA256 30:45:02:21:00:9E:44:EF:72:6F:33:C6:3B:1D:4D:6F: 78:9E:CF:95:66:DB:C6:B7:6D:C3:6C:FD:C3:DC:54:FB: BF:CD:02:53:6E:02:20:19:DB:E3:C6:00:07:6B:2E:30: CC:9C:BD:42:68:19:48:23:C9:1B:45:87:67:D9:4E:16: F1:B1:29:E7:17:96:90 Signature Algorithm: sha256WithRSAEncryption Signature Value: ad:7b:86:fe:42:9b:a1:fe:aa:be:07:7f:0a:63:1f:f2:8d:e2: eb:57:47:ce:37:4e:d3:d5:66:c3:bd:ca:f7:01:62:82:02:db: dc:3b:7a:73:13:cb:7e:99:48:f4:8f:b6:fb:72:bd:c6:4b:b2: 88:d4:a0:84:29:66:88:4f:3e:01:9b:11:a6:e7:11:8b:58:59: 62:b7:24:8f:9d:80:71:26:7d:59:7c:da:06:cb:0c:30:3b:57: 8a:99:a0:f7:5d:ac:cf:77:23:06:a7:04:85:9c:1b:c6:46:b9: 23:c8:a1:d0:f0:0f:54:45:f3:b1:92:53:6e:89:15:0f:53:5b: e1:27:c9:b8:3a:a0:88:10:11:98:b8:b0:1e:2e:ff:6f:e4:46: b5:f1:e4:1a:c8:88:60:80:fa:54:25:cf:0e:f5:a0:8d:ae:3f: a8:17:59:b5:81:be:43:0d:0a:f0:8a:ae:d3:1d:29:19:ec:2a: e2:de:91:bb:23:1a:4c:e0:63:e4:3b:e1:22:e4:13:a8:d1:56: c6:3e:62:b9:39:59:a6:43:d4:ae:0f:41:28:9c:91:c3:47:eb: fd:a2:b1:a9:81:db:5c:f7:3b:54:05:76:da:4d:ac:a2:4d:a2: 85:df:6e:5f:92:69:87:30:8c:e3:b6:ff:5e:15:68:e9:25:fb: 3d:0e:c3:46
Shell
복사
이번엔 x509이란 서브 명령을 썼는데 이것 무엇일까?
TLS 인증에 사용되는 공개 키 기반(PKI)의 표준이다. 오늘날 사용하는 인증서는 다 이 표준을 따른다고 보면 된다. 위의 출력 구조를 보면 크게 인증서, 서명 알고리즘, 서명 값 등이 보인다.
이 값들은 앞서 브라우저에서 본 인증서의 세부 사항 내용과 일치한다. 비교적 눈에 잘 보이는 subject DN, 발급자 DN부터 그 다음인 공개키 정보(Subject Public Key Info)를 매칭해볼 수 있다.
긴 X509 전체 구조가 아닌, 원하는 부분만 출력할 수 있다. 예를 들어 공개 키의 modulus 부분을 보고 싶으면, 전체를 출력하는 -text 대신, -modulus 옵션으로 명령하면 된다:
❯ openssl x509 -modulus -noout -in cre_ma.pem Modulus=CA1999A09AEC5F84D25AF30BEA95DD5C50411206A9F7554DC09C1717722631EE63178A822CB7946BFFBC258B950AC933E6C9DD923DB773FE64E3BB699D4FCDB471DC55933F70855BEDB6B97A4F639AAFD443371FD7D5FC50442E9FD270175FE63733FF9B24159C7BBC418D9BD5D535376DC497B772C5494DFF1D38781CC8F6FF8A48A1B6037DF4220C6790E29346E714D8474BE3BB4B457C90B35446F44B3DBFD0297E24A7CF41CD369410B04C6501F095BC0695C09F871E1C5D73661C85ADF270A1B0C4F5D602ADB4CD672E1408777A767685114E7EA892EB6685E10514A5213BB7A9F4E1B86BF0E9A5DE1EFC05B0F03860535A398E7379145954EC37DC2297
Plain Text
복사
이는 브라우저에서 보이는 공개키(256바이트)와 더 유사하다(위 -text 출력에서 나온 결과는 270바이트다). 이것은 RSA로 암호화된 공개키이다. RSA는 나중에 자세히 설명 한다.
더 많은 출력 방법은 openssl-x509 매뉴얼의 옵션을 참고(1.1.1 버전 매뉴얼이지만 3버전에서 하위 호환되고 이 페이지의 옵션 설명이 더 자세하다).
아직 모르는 부분이 많지만 X509 구조로 파싱해 본 결과 회사 인증서(subject)는 RSA 2048(256바이트)로 암호화 되었고 이를 확인했다. 그럼 서명(Signature)은 무엇일까? 이쯤에서 이 글을 읽고 오자.
https://gruuuuu.github.io/security/what-is-x509/
내가 직접 RSA 같은 해시 함수부터 인증서 체인의 개념까지 찾아보던 중 이 글이 전체 큰 그림을 잡는데 많은 도움이 됐다.

인증서 체인

정리하면, subject는 X509라는 PKI로 인증한다. 공개키는 뿌리고 비밀키를 subject가 가지고 있어 subject가 암호화한 데이터를 공개키로 복호화하여 본다. 이때 subject가 뿌린 공개키가 유효하다고 인증해 주는 것이 인증 기관(CA)이다. CA는 디지털 서명을 통해 인증서를 암호화해서 발급한다. CA 역시 인증서 형태로 공개키가 제공되는 구조이다. 이걸 Chain of Trust라 하고, 결국 만나는 최상위 루트 CA는 OS 또는 브라우저나 openssl 같은 프로그램에 내장되어 있다. 루트 CA 인증서는 모두가 신뢰한다고 가정한다.
여기서 인증 자체에 사용하는 암호화 알고리즘은 RSA이다:
❯ openssl x509 -text -noout -in cre_ma.pem | grep "Public Key Algorithm" Public Key Algorithm: rsaEncryption
Shell
복사
그리고 CA에서 서명 알고리즘은 SHA256이다:
❯ openssl x509 -text -noout -in cre_ma.pem | grep "Signature Algorithm" Signature Algorithm: sha256WithRSAEncryption Signature Algorithm: sha256WithRSAEncryption
Plain Text
복사
우리 예제에서 CA와 subject 인증서는 다음과 같다: - 루트: DigiCert Global Root CA - 중간자: DigiCert TLS RSA SHA256 2020 CA1 - subject: *.cre.ma
상위 CA 서명이라는 chain 때문에 인증서를 더 자세하게 들여다 보는건 어렵다(CA의 서명 비밀키가 있어야 인증서 복호화가 가능할 것이다). 대신 openssl 명령을 통해 chain 과정이 어떻게 되는지 또 각 CA의 모든 인증서가 어디에 위치하는지 찾아보자.

SSL handshake

HTTPS로 통신하면 TCP 연결을 맺는 3 way handshake 후에 SSL handshake를 맺어 인증서를 교환 후 통신한다. 사실 이 과정은 openssl s_client -connect 할 때에도 맺어졌는데, 여기에 -msg 옵션을 주면 디버그 해볼 수 있다. >>>는 클라이언트에서 서버 반대로 <<<는 서버에서 클라이언트로 보내는 메세지 종류를 보여준다. 패킷은 덤프하지 않을거라 생략했다(나중에 tcpdump 사용법을 익히면 해볼것!). 이번엔 인증 체인 depth를 보여주는 표준 에러도 표시하지 않았다:
❯ openssl s_client -connect cre.ma:443 -msg 2>/dev/null < /dev/null | grep Handshake>>> TLS 1.3, Handshake [length 0133], ClientHello<<< TLS 1.3, Handshake [length 0045], ServerHello<<< TLS 1.2, Handshake [length 0b29], Certificate<<< TLS 1.2, Handshake [length 012c], ServerKeyExchange<<< TLS 1.2, Handshake [length 0004], ServerHelloDone>>> TLS 1.2, Handshake [length 0025], ClientKeyExchange>>> TLS 1.2, Handshake [length 0010], Finished<<< TLS 1.2, Handshake [length 00ca], NewSessionTicket<<< TLS 1.2, Handshake [length 0010], Finished
Shell
복사
SSL handshake 과정 설명은 이 글로 대체한다

중간자 인증서

s_client 명령에 -showcerts 옵션을 추가하면 subject 뿐만 아니라 중간자 인증서도 확인할 수 있다(결과에서 중복 부분은 제거하고 중간자 인증서만 보이게 함):
❯ openssl s_client -connect cre.ma:443 -showcerts < /dev/null...Certificate chain...1 s:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1 i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Sep 24 00:00:00 2020 GMT; NotAfter: Sep 23 23:59:59 2030 GMT-----BEGIN CERTIFICATE-----MIIE6jCCA9KgAwIBAgIQCjUI1VwpKwF9+K1lwA/35DANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0yMDA5MjQwMDAwMDBaFw0zMDA5MjMyMzU5NTlaME8xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBSU0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6aqXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddng9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuWraKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGBAfr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21reacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBrjCCAaowHQYDVR0OBBYEFLdrouqoqoSMeeq02g+YssWVdrn0MB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDB7BgNVHR8EdDByMDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMDegNaAzhjFodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMDAGA1UdIAQpMCcwBwYFZ4EMAQEwCAYGZ4EMAQIBMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQELBQADggEBAHert3onPa679n/gWlbJhKrKW3EX3SJH/E6f7tDBpATho+vFScH90cnfjK+URSxGKqNjOSD5nkoklEHIqdninFQFBstcHL4AGw+oWv8Zu2XHFq8hVt1hBcnpj5h232sb0HIMULkwKXq/YFkQZhM6LawVEWwtIwwCPgU7/uWhnOKK24fXSuhe50gG66sSmvKvhMNbg0qZgYOrAKHKCjxMoiWJKiKnpPMzTFuMLhoClw+dj20tlQj7T9rxkTgl4ZxuYRiHas6xuwAwapu3r9rxxZf+ingkquqTgLozZXq8oXfpf2kUCwA/d5KxTVtzhwoT0JzI8ks5T1KESaZMkE4f97Q=-----END CERTIFICATE-----...
Shell
복사
명시적으로 인증서 체인을 증명 해보기 위해 복사하여 파일로 저장해두자:
cat DigiCert-TLS-RSA-SHA256-2020-CA1.pem-----BEGIN CERTIFICATE-----MIIE6jCCA9KgAwIBAgIQCjUI1VwpKwF9+K1lwA/35DANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0yMDA5MjQwMDAwMDBaFw0zMDA5MjMyMzU5NTlaME8xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBSU0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6aqXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddng9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuWraKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGBAfr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21reacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBrjCCAaowHQYDVR0OBBYEFLdrouqoqoSMeeq02g+YssWVdrn0MB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDB7BgNVHR8EdDByMDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMDegNaAzhjFodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMDAGA1UdIAQpMCcwBwYFZ4EMAQEwCAYGZ4EMAQIBMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQELBQADggEBAHert3onPa679n/gWlbJhKrKW3EX3SJH/E6f7tDBpATho+vFScH90cnfjK+URSxGKqNjOSD5nkoklEHIqdninFQFBstcHL4AGw+oWv8Zu2XHFq8hVt1hBcnpj5h232sb0HIMULkwKXq/YFkQZhM6LawVEWwtIwwCPgU7/uWhnOKK24fXSuhe50gG66sSmvKvhMNbg0qZgYOrAKHKCjxMoiWJKiKnpPMzTFuMLhoClw+dj20tlQj7T9rxkTgl4ZxuYRiHas6xuwAwapu3r9rxxZf+ingkquqTgLozZXq8oXfpf2kUCwA/d5KxTVtzhwoT0JzI8ks5T1KESaZMkE4f97Q=-----END CERTIFICATE-----
Shell
복사
x509 명령으로 공개키를 파싱할 수 있다:
❯ openssl x509 -pubkey -noout -in DigiCert-TLS-RSA-SHA256-2020-CA1.pem > DigiCert-TLS-RSA-SHA256-2020-CA1.pub.pem❯ cat DigiCert-TLS-RSA-SHA256-2020-CA1.pub.pem-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6aqXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddng9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuWraKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGBAfr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21reacroicgE7XQPUDTITAHk+qZ9QIDAQAB-----END PUBLIC KEY-----
Shell
복사

루트 인증서

루트 인증서는 OS 또는 프로그램에 내장되어 있다고 했다. openssl의 경우 /usr/local/etc/openssl@3/certs/cert.pem를 바라보고 있다. 우리 예제의 루트인 DigiCert Global Root CA도 찾을 수 있다.
grep Digi /usr/local/etc/openssl@3/certs/cert.pemDigiCert Assured ID Root CADigiCert Global Root CADigiCert High Assurance EV Root CADigiCert Assured ID Root G2DigiCert Assured ID Root G3DigiCert Global Root G2DigiCert Global Root G3DigiCert Trusted Root G4❯ grep -A 20 "DigiCert Global Root CA" /usr/local/etc/openssl@3/certs/cert.pemDigiCert Global Root CA=======================-----BEGIN CERTIFICATE-----MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQkCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=-----END CERTIFICATE-----
Shell
복사
이번에도 개별 인증서와 공개키를 파일로 저장하자:
cat DigiCert-Global-Root-CA.pem-----BEGIN CERTIFICATE-----MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQkCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=-----END CERTIFICATE-----❯ openssl x509 -pubkey -noout -in DigiCert-Global-Root-CA.pem > DigiCert-Global-Root-CA.pub.pem❯ cat DigiCert-Global-Root-CA.pub.pem-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB-----END PUBLIC KEY-----
Shell
복사

인증서 증명

증명에 필요한 모든 상위 CA 인증서와 subject 인증서가 준비됐다. 명시적으로 모든 상위 인증서를 사용하여 증명해보면:
❯ openssl verify -CAfile DigiCert-Global-Root-CA.pem -untrusted DigiCert-TLS-RSA-SHA256-2020-CA1.pem cre_ma.pemcre_ma.pem: OK
Shell
복사
CAfile 옵션엔 루트 인증서를 주고 untrusted 옵션엔 중간자 인증서를 줬다. untrusted라는 이름이 좀 난해하지만 매뉴얼을 보면 정확히 중간자 인증서 역할이다 :
-untrusted filename|uri A file or URI of untrusted certificates to use for chain building. This option can be specified more than once to load certificates from multiple sources.
Plain Text
복사
openssl 루트 CA에 DigiCert Global Root CA가 이미 있기 때문에 -CAfile 옵션은 빼도 무방하다. 다른 루트 인증서를 옵션으로 주면 증명이 실패하게 된다.

정리

openssl s_client 명령으로 SSL handshake 및 세션과 인증서를 확인할 수 있다.
openssl x509 명령으로 인증서를 파싱할 수 있다.
전체적인 과정에 두가지 암호화가 있다
SSL/TLS 인증 암호화 PKI로 한다. PKI의 공개키가 인증서이다. PKI 표준 이름은 X509이고, 암호 알고리즘은 RSA.
Chain of Trust를 위해 CA에서 인증서(공개키)에 디지털 서명(암호화)하여 발급한다. 여기서 암호 알고리즘은 SHA256
한 포스팅에 쓰려고 했는데 예상보다 길어져서 글을 나눈다. 원래 쓰려던 분량은 3편 정도면 충분하지만, 이 글을 쓰면서 인증 매커니즘인 PKI와 디지털 서명 부분을 헷갈린다는 걸 알았다. 그래서 다 쓰면 나중에 4~5편도 나올 수 있지만 일단 3부작까지 끝내 보려고 함… 시간이 굉장히 오래 걸렸지만 글로 쓰는 순간에도 어떤걸 알고 어떤걸 모르는지 정리가 되어 쓰기 잘했단 생각이 든다(덤으로 openssl 명령이 손에 익어버렸다).
다음 글에선 A self-signed certificate이란 이름으로 많이 알려진 방법을 써서 CA에서 어떻게 인증서를 발급하는지 직접 해볼 것이다.