Self Signed 인증서 만들기
이 포스팅은 Self Signed 인증서 만들기 간략한 버전이다. 이론적인 내용은 빼고 OpenSSL 을 이용해서 만드는 방법을 설명한다.
만들기 순서
Self Signed 인증서 만들때에는 순서가 있다.
- root CA 를 위한 비밀키 생성(비대칭키)
- root 인증서 생성 위한 CSR 생성
- root 인증서 생성
- Server 인증서를 위한 비밀키 생성(비대칭키)
- Server 인증서 생성을 위한 CSR 생성
- Server 인증서 생성
대략 위와 같은 순서를 따른다. 비대칭 비밀키를 생성을 위해서 openssl 명령어를 사용한다. 글의 진행을 위해서 a.com 도메인에 대한 인증서를 생성하는 것으로 가정한다.
v3 확장
한가지 알고 가야할 것이 x509 표준에 v3 확장이다. 이 확장은 인증서에 대한 버전을 말하는 것으로 현재 Version 3 에서 확장(Extend) 된 것을 말한다.
v3 확장을 이용하면 SAN(Subject Alternative Name) 을 포함한 인증서를 생성할 수 있다.
이러한 확장을 이용하기 위해서 일종의 명세서 파일을 이용하게 되는데, 인증서 생성에 있어서 이 명세서 파일이 핵심이라고 할 수 있다. CSR 및 인증서 생성에 명세서 파일이 사용된다고 할 수 있다.
root CA 를 위한 비밀키 생성
openssl 를 이용해서 root CA 를 위한 비밀키를 다음과 같이 생성한다.
1 |
openssl genrsa -out RootCA-key.pem 2048 |
비밀키가 정상적으로 생성이 된다. 생성된 비밀키에 대한 정보는 다음의 명령어로 확인이 가능하다.
1 2 3 4 5 6 7 |
$ openssl rsa -in RootCA-key.pem -check RSA key ok writing RSA key -----BEGIN PRIVATE KEY----- $ openssl rsa -in RootCA-key.pem -noout -text Private-Key: (2048 bit, 2 primes) modulus: |
참고로 비밀키를 이용해서 공개키(Public Key) 를 생성할 수 있는데, 다음과 같다.
1 2 |
$ openssl rsa -inform PEM -in rootCA-key.pem -pubout -outform PEM -out rootCA-public-key.pem writing RSA key |
root 인증서 생성 위한 CSR 생성
CSR 파일을 생성하기 명세서 파일을 이용한다. 명세서 파일은 CSR 만 아니라 인증서 생성에도 사용된다. 명세서 파일을 rootCA.cnf 이름으로 생성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
[req] default_bits = 2048 default_md = sha256 default_keyfile = RootCA-key.pem distinguished_name = dn req_extensions = v3_req x509_extensions = v3_ca [ v3_req ] basicConstraints = critical, CA:TRUE subjectKeyIdentifier = hash [ v3_ca ] basicConstraints = critical, CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer keyUsage = critical, cRLSign, digitalSignature, keyCertSign extendedKeyUsage = clientAuth, serverAuth [dn] countryName = Country Name (2 letter code) countryName_default = KR countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name stateOrProvinceName_default = Magokjungang 8-ro, Gangseo-gu localityName = Locality Name localityName_default = Seoul organizationName = Organization Name (eg, company) organizationName_default = Systemv organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = AI commonName = Common Name (eg, your name or your server's hostname) commonName_default = a.com commonName_max = 64 emailAddress = Email Address emailAddress_default = linux@a.com emailAddress_max = 64 |
위 명세서는 아무렇게나 만는게 아니며 정해진 규칙이 있다. dn 섹션에는 CSR 작성시 입력할 인증서에 대한 요청자 정보를 입력하는 필드를 지정할 수 있다.
이제 RootCA.cnf 명세서 파일을 이용해서 CSR 파일을 다음과 같이 작성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ openssl req -new -key RootCA-key.pem -out RootCA.csr -config RootCA.cnf You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [KR]: State or Province Name [Magokjungang 8-ro, Gangseo-gu]: Locality Name [Seoul]: Organization Name (eg, company) [Systemv]: Organizational Unit Name (eg, section) [AI]: Common Name (eg, your name or your servers hostname) [a.com]: Email Address [linux@a.com]: |
명세서에 dn 섹션에 내용을 출력하고 있다. CSR 파일이 생성이 되었다.
root 인증서 생성
이제 지금까지 생성된 비밀키와 CSR 파일을 이용해 인증서를 생성한다. 인증서를 생성할때에는 인증서의 사용기간을 정해야 한다.
1 2 3 4 |
$ openssl x509 -req -days 730 -extensions v3_ca -set_serial 1 -in RootCA.csr -signkey RootCA-key.pem -out RootCA.crt -extf ile RootCA.cnf Certificate request self-signature ok subject=C = KR, ST = "Magokjungang 8-ro, Gangseo-gu", L = Seoul, O = Systemv, OU = AI, CN = a.com, emailAddress = linux@a.com |
인증서의 사용기간은 730 일이다. 그리고 -extensions v3_ca 를 인자로 줬는데, 명세서 파일인 RootCA.cnf 파일에 v3_ca 섹션을 사용하라는 뜻이다. v3_ca 섹션에는 인증서에 대한 사용범위, RootCA 임을 증명하는 CA:TRUE 등이 있다.
확인은 다음과 같이 할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
$ openssl x509 -in RootCA.crt -noout -text Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C = KR, ST = "Magokjungang 8-ro, Gangseo-gu", L = Seoul, O = Systemv, OU = AI, CN = a.com, emailAddress = linux@a.com Validity Not Before: Feb 28 05:58:12 2025 GMT Not After : Feb 28 05:58:12 2027 GMT Subject: C = KR, ST = "Magokjungang 8-ro, Gangseo-gu", L = Seoul, O = Systemv, OU = AI, CN = a.com, emailAddress = linux@a.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:f2:c8:c0:76:9d:13:e5:cf:1b:4e:9f:68:0b:93: b9:06:12:af:a4:f1:50:3a:87:f4:95:27:f6:d0:1e: 6b:ff:cf:0f:74:a8:da:7d:a3:d4:04:dd:f4:7d:a8: b1:68:db:3e:32:82:4a:ab:31:f9:da:22:db:fd:59: fc:93:0d:f2:51:41:ec:6a:25:7b:c7:ca:9a:43:57: 50:64:29:b5:79:21:b9:9d:5c:c4:3e:fd:e1:c9:fc: e7:11:40:81:fc:60:8a:42:df:5b:7a:27:5e:5b:7c: fb:8f:49:55:ea:00:ce:32:e4:b4:18:2f:e7:b5:6b: 59:1f:e5:30:75:eb:47:56:6f:ba:01:a2:82:23:4e: e7:c7:7f:a8:c3:4d:c7:28:f3:aa:bd:46:0c:f4:75: 88:68:ea:4f:2d:0b:9c:33:df:03:73:9e:76:14:33: f8:2f:e3:27:e8:cd:3a:77:c6:d4:e1:98:6a:0b:b2: 57:f7:89:08:ad:8b:10:e3:47:70:85:3d:e0:9f:b6: 67:a4:1f:87:b9:95:3c:07:bc:8f:16:7b:8b:0a:05: db:a9:d9:12:dd:3c:33:74:26:16:d4:16:d4:c5:db: bc:ae:7f:e9:cf:89:19:38:76:57:fe:b3:db:59:b1: fd:96:51:bf:82:d5:25:4e:c2:ec:4f:3f:97:5f:27: cb:01 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical CA:TRUE X509v3 Subject Key Identifier: 4D:D5:A8:E9:42:7B:4E:66:10:1A:34:7B:87:4A:B6:DD:0E:7B:EC:2F X509v3 Authority Key Identifier: 4D:D5:A8:E9:42:7B:4E:66:10:1A:34:7B:87:4A:B6:DD:0E:7B:EC:2F X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign X509v3 Extended Key Usage: TLS Web Client Authentication, TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption Signature Value: 64:23:20:4d:4f:af:01:56:8e:a8:eb:67:5f:38:87:0c:6f:b3: 2f:32:66:f3:ff:38:15:20:bb:15:8e:b1:ac:3c:77:36:37:b3: c6:92:13:a7:df:75:eb:b3:2f:4b:b0:16:b4:f5:9d:18:7f:5f: 6f:e1:4f:31:e0:37:e4:43:5f:0c:36:d0:9f:92:0a:b3:30:b0: 70:d4:73:d7:a6:fb:76:3d:29:b4:74:d0:ec:57:13:57:85:d7: 80:14:88:dc:48:a6:c8:91:da:35:3e:bd:75:c3:d3:e3:31:84: 0c:a9:e5:5b:63:57:56:36:6e:94:1d:83:3a:cc:11:b0:12:92: 69:12:e9:55:17:04:3a:8c:c1:42:d6:ad:6b:8e:26:26:38:b1: 06:70:51:a8:d5:cc:6a:c0:05:01:43:b1:27:f9:7a:43:b2:58: 38:41:5a:56:07:76:a8:e4:4e:a9:1e:b5:f8:ac:37:a8:68:ec: 36:25:77:76:59:41:b3:d2:aa:d3:9c:6c:9f:88:c1:56:96:84: c7:39:45:2c:8d:c7:fa:d4:e0:3b:36:3e:d8:f9:ce:cf:b0:f3: a4:c6:76:00:73:f7:aa:b8:ce:87:69:6c:50:00:5c:81:b7:40: c5:cc:9e:b7:1c:91:2d:b5:ce:35:86:83:0a:33:39:39:97:77: 9d:1c:c6:b8 |
Server 인증서를 위한 비밀키 생성(비대칭키)
이제 서버 인증서를 생성해야 한다. 서버 인증서를 위한 비밀키를 다음과 같이 생성한다.
1 |
$ openssl genrsa -out server-key.pem 2048 |
Server 인증서 생성을 위한 CSR 생성
이제 서버 인증서 생성을 위한 명세서 파일을 server.cnf 파일 이름으로 다음과 같이 생성 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
[req] default_bits = 2048 default_md = sha256 distinguished_name = dn req_extensions = v3_req x509_extensions = v3_ca [ v3_req ] basicConstraints = critical, CA:FALSE subjectKeyIdentifier = hash [ v3_ca ] basicConstraints = critical, CA:FALSE subjectAltName = @alt_names subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer keyUsage = critical, digitalSignature extendedKeyUsage = clientAuth, serverAuth [dn] countryName = Country Name (2 letter code) countryName_default = KR countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Magokjungang 8-ro, Gangseo-gu localityName = Locality Name (eg, city) localityName_default = Seoul organizationName = Organization Name (eg, company) organizationName_default = Systemv organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = AI commonName = Common Name (eg, server FQDN or YOUR name) commonName_default = a.com commonName_max = 64 emailAddress = Email Address emailAddress_default = linux@a.com emailAddress_max = 64 [alt_names] DNS.1 = a.com DNS.2 = *.a.com IP.1 = 127.0.0.1 |
RootCA 인증서와 차이점이 보인다. alt_names 섹션이 추가 되었다. 그리고 CA:FALSE 이며 keyUsage 도 다르다. 이 명세서를 이용해서 서버인증서를 위한 CSR 를 생성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ openssl req -new -key server-key.pem -out server.csr -config server.cnf You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [KR]: State or Province Name (full name) [Magokjungang 8-ro, Gangseo-gu]: Locality Name (eg, city) [Seoul]: Organization Name (eg, company) [Systemv]: Organizational Unit Name (eg, section) [AI]: Common Name (eg, server FQDN or YOUR name) [a.com]: Email Address [linux@a.com]: |
예제를 위해서 CSR 입력 내용이 RootCA 와 동일하지만 공인 인증서는 서버CSR 입력 내용이 RootCA 와 같을 수가 없다.
Server 인증서 생성
이제 Server 비밀키와 CSR, RootCA 인증서, RootCA 비밀키를 이용해서 Server 인증서를 생성한다.
1 2 3 |
openssl x509 -req -in server.csr -CA RootCA.crt -CAkey RootCA-key.pem -CAcreateserial -out server.crt -days 730 -extensions v3_ca -sha256 -extfile server.cnf Certificate request self-signature ok subject=C = KR, ST = "Magokjungang 8-ro, Gangseo-gu", L = Seoul, O = Systemv, OU = AI, CN = a.com, emailAddress = linux@a.com |
생성된 인증서를 확인해 보면 CA:FALSE 로 나타나고, Subject Alternative Name 이 명세서에 내용과 같다.
PKCS12 포맷 인증서 변경
PKCS12 포맷은 Java 시스템에서 사용하는 인증서 포맷이다. 앞서 생성한 인증서는 PEM 포맷 인증서라서 Java 시스템에서 바로 이용할 수 없다. PEM 파일이 있다면 PCKS 포맷 인증서로 변경이 가능하다.
1 2 3 |
$ openssl pkcs12 -export -out keystore.p12 -inkey server-key.pem -in server.crt -name aiwire Enter Export Password: Verifying - Enter Export Password: |
-name 은 Alias Name 을 말한다. 패스워드를 지정하지 않을려면 입력하지 않고 엔터만 치면 된다.
제대로 되었는지 다음과 같이 확인할 수 있다.
1 2 |
$ keytool -list -v -keystore keystore.p12 -storetype pkcs12 Enter keystore password: |
SpringBoot 에서는 다음과 같이 application.properties 에 다음과 같이 사용할 수 있다.
1 2 3 4 5 |
#SSL server.ssl.key-alias=aiwire server.ssl.key-store=classpath:keystore.p12 server.ssl.key-store-type=PKCS12 server.ssl.key-store-password=12345 |