[ssl] OpenSSL을 사용하여 자체 서명 된 인증서를 만드는 방법

임베디드 Linux 장치에 HTTPS 지원을 추가하고 있습니다. 다음 단계를 통해 자체 서명 된 인증서를 생성하려고했습니다.

openssl req -new > cert.csr
openssl rsa -in privkey.pem -out key.pem
openssl x509 -in cert.csr -out cert.pem -req -signkey key.pem -days 1001
cat key.pem>>cert.pem

작동하지만 Chrome과 같은 오류가 발생합니다.

이것은 아마도 당신이 찾고있는 사이트가 아닙니다!
사이트의 보안 인증서를 신뢰할 수 없습니다!

뭔가 빠졌습니까? 이것이 자체 서명 된 인증서를 작성하는 올바른 방법입니까?



답변

하나의 명령으로 그렇게 할 수 있습니다.

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

암호를 사용하여 개인 키를 보호하지 않으려는 경우을 추가 할 수도 있습니다 -nodes(약칭 no DES). 그렇지 않으면 “최소 4 자”암호를 묻는 메시지가 나타납니다.

days어떤 번호로 대체 할 수있는 매개 변수 (365)는 유효 기간에 영향을 미칠 수 있습니다. 그런 다음 “국가 이름”과 같은 메시지가 표시되지만 Enter기본값을 누르고 적용 할 수 있습니다 .

-subj '/CN=localhost'인증서 내용에 대한 질문을 표시하지 않으려면 추가 localhost하십시오 (원하는 도메인으로 교체 ).

자체 서명 된 인증서는 이전에 브라우저로 가져 오지 않는 한 타사에서 유효성을 검증하지 않습니다. 더 많은 보안이 필요한 경우 인증 기관 (CA)에서 서명 한 인증서를 사용해야합니다 .


답변

뭔가 빠졌습니까? 이것이 자체 서명 된 인증서를 작성하는 올바른 방법입니까?

자체 서명 된 인증서를 쉽게 만들 수 있습니다. 당신은 openssl req명령을 사용합니다 . 브라우저 및 명령 줄 도구와 같이 가장 다양한 클라이언트가 사용할 수있는 클라이언트를 만드는 것은 까다로울 수 있습니다.

브라우저에는 자체 요구 사항이 있으며 IETF 보다 제한적이므로 어렵습니다 . 브라우저가 사용하는 요구 사항은 CA / 브라우저 포럼에 설명되어 있습니다 (아래 참조 참조). 제한 사항은 (1) 트러스트 앵커 및 (2) DNS 이름의 두 가지 주요 영역에서 발생합니다.

최신 브라우저 (2014/2015에서 사용중인 warez와 같은)는 트러스트 앵커에 연결되는 인증서를 원하며 인증서에서 특정 방식으로 DNS 이름을 제시하기를 원합니다. 그리고 브라우저는 자체 서명 된 서버 인증서에 대해 적극적으로 움직이고 있습니다.

일부 브라우저에서는 자체 서명 된 서버 인증서를 쉽게 가져올 수 없습니다. 실제로 Android 브라우저와 같은 일부 브라우저에서는 사용할 수 없습니다. 따라서 완전한 해결책은 자신의 권한이되는 것입니다.

자신의 권한이없는 경우 인증서의 성공 가능성을 높이려면 DNS 이름을 가져와야합니다. 그러나 나는 당신이 당신의 자신의 권위가 되길 바랍니다. 자신의 권위가되기가 쉬우 며 모든 신뢰 문제를 회피 할 것입니다 (자신보다 신뢰하는 것이 더 나은가?).


이것은 아마도 당신이 찾고있는 사이트가 아닙니다!
사이트의 보안 인증서를 신뢰할 수 없습니다!

브라우저는 미리 정의 된 트러스트 앵커 목록을 사용하여 서버 인증서의 유효성을 검사하기 때문입니다. 자체 서명 된 인증서는 신뢰할 수있는 앵커에 다시 연결되지 않습니다.

이것을 피하는 가장 좋은 방법은 다음과 같습니다.

  1. 자신의 권한을 만듭니다 (즉, CA가 됨 )
  2. 서버에 대한 인증서 서명 요청 (CSR) 작성
  3. CA 키로 서버의 CSR에 서명
  4. 서버에 서버 인증서를 설치하십시오.
  5. 클라이언트에 CA 인증서 설치

1 단계- 자신의 권한 을 생성하는 것은 CA: true적절한 키 사용과 자체 서명 된 인증서를 생성하는 것을 의미 합니다. 즉, 주체발급자 가 동일한 엔터티이고 CA가 기본 제약 조건 에서 중요로 설정되어 있고 (중요로 표시되어야 함) 키 사용이 keyCertSign있고 crlSign(CRL을 사용하는 경우) 주체 키 식별자 (SKI)가 권한 키 식별자 (AKI) 와 동일합니다 .

자체 인증 기관이 되려면 * 인증 기관 에 인증서 서명 요청에 어떻게 서명합니까?를 참조하십시오. 스택 오버플로. 그런 다음 브라우저에서 사용하는 신뢰 저장소로 CA를 가져 오십시오.

2-4 단계는 Startcom 또는 CAcert 와 같은 CA의 서비스를 등록 할 때 공용 서버에 대해 대략 수행하는 작업 입니다. 1 단계와 5 단계를 사용하면 제 3 자 권한을 피하고 자신의 권한으로 행동 할 수 있습니다 (자신보다 신뢰하는 것이 더 낫습니까?).

브라우저 경고를 피하는 다음 가장 좋은 방법은 서버의 인증서를 신뢰하는 것입니다. 그러나 Android의 기본 브라우저와 같은 일부 브라우저는 허용하지 않습니다. 따라서 플랫폼에서 작동하지 않습니다.

자체 서명 된 인증서를 신뢰 하지 않는 브라우저 (및 기타 유사한 사용자 에이전트)의 문제는 사물 인터넷 (IoT)에서 큰 문제가 될 것입니다. 예를 들어 서모 스탯이나 냉장고에 연결하여 프로그래밍하면 어떻게됩니까? 대답은 사용자 경험에 관한 한 아무 것도 아닙니다.

W3C의 WebAppSec 실무 그룹이이 문제를 살펴보기 시작했습니다. 예를 들어 제안 : HTTP를 비보안으로 표시 를 참조하십시오 .


OpenSSL을 사용하여 자체 서명 된 인증서를 만드는 방법

아래 명령과 구성 파일은 자체 서명 인증서를 작성합니다 (서명 요청 작성 방법도 표시 함). 자체 서명 된 인증서에 사용 된 DNS 이름은 CN (일반 이름)이 아니라 SAN (주체 대체 이름 )에 있습니다.

DNS 이름은 구성 파일을 통해 SAN에 배치됩니다 subjectAltName = @alternate_names(명령 행을 통해 수행 할 수있는 방법은 없습니다). 그런 다음 alternate_names구성 파일에 섹션이 있습니다 (사용자의 취향에 맞게 조정해야 함).

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# IP.1        = 127.0.0.1
# IP.2        = ::1

이 때문에 SAN이 아닌 CN에서 DNS 이름을 넣어하는 것이 중요 모두 는 IETF와 CA는 / 브라우저 포럼 연습을 지정합니다. 또한 CN의 DNS 이름은 더 이상 사용되지 않도록 지정하지만 금지되지는 않습니다. 경우 당신이 CN의 DNS 이름을 넣어, 다음은 해야한다 는 CA / B 정책 아래에있는 SAN에 포함. 따라서 주체 대체 이름 사용을 피할 수 없습니다.

SAN에 DNS 이름을 입력하지 않으면 CA / 브라우저 포럼 지침을 따르는 브라우저 및 기타 사용자 에이전트에서 인증서의 유효성이 검사되지 않습니다.

관련 : 브라우저는 CA / Browser Forum 정책을 따릅니다. IETF 정책이 아닙니다. 이것이 OpenSSL로 생성 된 인증서 (일반적으로 IETF를 따르는)가 때때로 브라우저에서 유효성을 검사하지 않는 이유 중 하나입니다 (브라우저는 CA / B를 따릅니다). 그들은 서로 다른 표준이며, 발행 정책과 검증 요구 사항이 다릅니다.


자체 서명 인증서를 작성하십시오 ( -x509옵션 추가에 유의).

openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.cert.pem

서명 요청을 작성하십시오 ( -x509옵션 이 없음에 유의하십시오).

openssl req -config example-com.conf -new -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.req.pem

자체 서명 인증서를 인쇄하십시오 .

openssl x509 -in example-com.cert.pem -text -noout

서명 요청을 인쇄하십시오 .

openssl req -in example-com.req.pem -text -noout

구성 파일 ( -config옵션을 통해 전달 )

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because it's presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = test@example.com

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier    = keyid,issuer

# You only need digitalSignature below. *If* you don't allow
#   RSA Key transport (i.e., you use ephemeral cipher suites), then
#   omit keyEncipherment because that's key transport.
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage    = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage    = serverAuth, clientAuth

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

Chrome에 대해 다음을 수행해야 할 수 있습니다. 그렇지 않으면 Chrome에서 일반 이름 이 잘못 되었다고 불평 할 수 있습니다 ( ERR_CERT_COMMON_NAME_INVALID) . SAN의 IP 주소와이 인스턴스의 CN 사이의 관계가 무엇인지 잘 모르겠습니다.

# IPv4 localhost
# IP.1       = 127.0.0.1

# IPv6 localhost
# IP.2     = ::1

X.509 / PKIX 인증서의 DNS 이름 처리에 관한 다른 규칙이 있습니다. 규칙은 다음 문서를 참조하십시오.

RFC 6797 및 RFC 7469는 다른 RFC 및 CA / B 문서보다 제한적이므로 나열되어 있습니다. RFC 6797 및 7469 IP 주소도 허용 하지 않습니다 .


답변

여기에 설명 된 옵션입니다 diegows의 대답 @ 에서 자세히 설명, 문서는 :

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX
req

PKCS # 10 인증서 요청 및 인증서 생성 유틸리티.

-x509

이 옵션은 인증서 요청 대신 자체 서명 된 인증서를 출력합니다. 일반적으로 테스트 인증서 또는 자체 서명 된 루트 CA를 생성하는 데 사용됩니다.

-newkey arg

이 옵션은 새 인증서 요청 및 새 개인 키를 작성합니다. 논쟁은 여러 형태 중 하나를 취합니다. rsa : nbits (여기서 nbits 는 비트 수임) RSA 키 nbit 크기를 생성합니다 .

-keyout filename

새로 만든 개인 키를 쓸 파일 이름을 제공합니다.

-out filename

기본적으로 쓸 출력 파일 이름 또는 표준 출력을 지정합니다.

-days n

-x509 옵션이 지정을 사용하고있는 일의 수에 대한 인증서를 인증합니다. 기본값은 30 일입니다.

-nodes

이 옵션이 지정되면 개인 키가 작성되면 암호화되지 않습니다.

문서는 실제로 위보다 더 자세합니다. 방금 요약했습니다.


답변

2020 년부터 다음 명령은 SAN을 포함하여 모든 요구를 충족시킵니다.

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout example.key -out example.crt -extensions san -config \
  <(echo "[req]";
    echo distinguished_name=req;
    echo "[san]";
    echo subjectAltName=DNS:example.com,DNS:example.net,IP:10.0.0.1
    ) \
  -subj "/CN=example.com"

OpenSSL ≥ 1.1.1에서는 다음과 같이 단축 될 수 있습니다.

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout example.key -out example.crt -subj "/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:example.net,IP:10.0.0.1"

그것은 인증서를 만듭니다

  • 도메인 example.comexample.net(SAN)에 유효
  • IP 주소 10.0.0.1(SAN) 에도 유효합니다.
  • 비교적 강함 (2020 년 기준)
  • 3650일 (~ 10 년) 동안 유효합니다 .

다음 파일을 작성합니다.

  • 개인 키 : example.key
  • 증명서: example.crt

모든 정보는 명령 행에 제공됩니다. 당신을 귀찮게하는 대화 형 입력없습니다 . 엉망인 설정 파일없습니다 . 필요한 모든 단계는 개인 키 생성에서 자체 서명 된 인증서에 이르기까지 단일 OpenSSL 호출 로 실행됩니다 .

비고 # 1 : 암호화 매개 변수

인증서는 자체 서명되어 있으며 사용자가 수동으로 승인해야하므로 짧은 만기 또는 약한 암호화를 사용하는 것은 적합하지 않습니다.

앞으로 4096RSA 키에 비트 이상의 비트 를 사용하고보다 강한 해시 알고리즘 을 사용할 수 sha256있지만 2020 년 기준으로 제정 된 값입니다. 모든 최신 브라우저에서 지원되는 동안 충분히 강력합니다.

비고 # 2 : 매개 변수 ” -nodes

이론적으로 -nodes매개 변수 ( “DES 암호화 없음”을 의미)를 생략 할 수 있으며,이 경우 example.key비밀번호로 암호화됩니다. 그러나 서버에 암호를 저장해야하거나 재부팅 할 때마다 수동으로 암호를 입력해야하므로 이는 서버 설치에 거의 유용하지 않습니다.

비고 # 3 : 참조


답변

나는 언급 할 수 없으므로 이것을 별도의 답변으로 넣을 것입니다. 허용되는 한 줄짜리 답변과 관련된 몇 가지 문제를 발견했습니다.

  • 원 라이너에는 키에 암호가 포함되어 있습니다.
  • 하나의 라이너는 많은 브라우저에서 콘솔에 경고를 발생시키는 SHA-1을 사용합니다.

다음은 암호 문구를 제거하고 경고를 억제하도록 보안을 강화하며 전체 질문 목록을 제거하기 위해 -subj에 전달할 주석에 제안을 포함하는 단순화 된 버전입니다.

openssl genrsa -out server.key 2048
openssl rsa -in server.key -out server.key
openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=localhost'
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

‘localhost’를 필요한 도메인으로 바꾸십시오. OpenSSL이 암호 문구를 요구하므로 처음 두 명령을 하나씩 실행해야합니다.

둘을 .pem 파일로 결합하려면 :

cat server.crt server.key > cert.pem


답변

최신 브라우저는 이제 제대로 구성된 자체 서명 된 인증서에 SAN (주체 대체 이름)이없는 경우 보안 오류가 발생합니다. OpenSSL은이를 지정하는 명령 줄 방법을 제공하지 않으므로 많은 개발자의 자습서 및 책갈피가 갑자기 오래되었습니다.

다시 실행하는 가장 빠른 방법은 짧은 독립형 conf 파일입니다.

  1. (예 : 측정은 OpenSSL 설정 파일을 작성 req.cnf)

    [req]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_req
    prompt = no
    [req_distinguished_name]
    C = US
    ST = VA
    L = SomeCity
    O = MyCompany
    OU = MyDivision
    CN = www.company.com
    [v3_req]
    keyUsage = critical, digitalSignature, keyAgreement
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = www.company.com
    DNS.2 = company.com
    DNS.3 = company.net
    
  2. 이 구성 파일을 참조하는 인증서를 작성하십시오.

    openssl req -x509 -nodes -days 730 -newkey rsa:2048 \
     -keyout cert.key -out cert.pem -config req.cnf -sha256
    

https://support.citrix.com/article/CTX135602의 구성 예


답변

주요 브라우저는 “SHA-1 인증서”를 안전하지 않은 것으로 표시하기 때문에 SHA-2 해시 알고리즘을 사용 하려면 -sha256 매개 변수 를 추가하는 것이 좋습니다 .

허용 된 답변과 동일한 명령 줄-추가 된 -sha256이있는 @diegows

openssl req -x509 -sha256 -newkey rsa : 2048 -keyout key.pem -out cert.pem-일 XXX

더 많은 정보를 구글 보안 블로그 .

업데이트 월 2018 사용하여 SHA-2는 자체 서명 된 인증서에 보안을 추가하지 않습니다 코멘트에서 언급 한 많은으로. 그러나 여전히 구식 / 안전하지 않은 암호화 해시 기능을 사용하지 않는 좋은 습관으로 사용하는 것이 좋습니다. 전체 엔터티 인증서 위의 인증서가 SHA-1 기반 인 것이 왜 좋은가? 에서 자세한 설명을 볼 수 있습니다 . .