How to generate a self-signed SSL certificate using OpenSSL?

2,372,224

Solution 1

You can do that in one command:

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

You can also add -nodes (short for no DES) if you don't want to protect your private key with a passphrase. Otherwise it will prompt you for "at least a 4 character" password.

The days parameter (365) you can replace with any number to affect the expiration date. It will then prompt you for things like "Country Name", but you can just hit Enter and accept the defaults.

Add -subj '/CN=localhost' to suppress questions about the contents of the certificate (replace localhost with your desired domain).

Self-signed certificates are not validated with any third party unless you import them to the browsers previously. If you need more security, you should use a certificate signed by a certificate authority (CA).

Solution 2

Am I missing something? Is this the correct way to build a self-signed certificate?

It's easy to create a self-signed certificate. You just use the openssl req command. It can be tricky to create one that can be consumed by the largest selection of clients, like browsers and command line tools.

It's difficult because the browsers have their own set of requirements, and they are more restrictive than the IETF. The requirements used by browsers are documented at the CA/Browser Forums (see references below). The restrictions arise in two key areas: (1) trust anchors, and (2) DNS names.

Modern browsers (like the warez we're using in 2014/2015) want a certificate that chains back to a trust anchor, and they want DNS names to be presented in particular ways in the certificate. And browsers are actively moving against self-signed server certificates.

Some browsers don't exactly make it easy to import a self-signed server certificate. In fact, you can't with some browsers, like Android's browser. So the complete solution is to become your own authority.

In the absence of becoming your own authority, you have to get the DNS names right to give the certificate the greatest chance of success. But I would encourage you to become your own authority. It's easy to become your own authority, and it will sidestep all the trust issues (who better to trust than yourself?).


This is probably not the site you are looking for!
The site's security certificate is not trusted!

This is because browsers use a predefined list of trust anchors to validate server certificates. A self-signed certificate does not chain back to a trusted anchor.

The best way to avoid this is:

  1. Create your own authority (i.e., become a CA)
  2. Create a certificate signing request (CSR) for the server
  3. Sign the server's CSR with your CA key
  4. Install the server certificate on the server
  5. Install the CA certificate on the client

Step 1 - Create your own authority just means to create a self-signed certificate with CA: true and proper key usage. That means the Subject and Issuer are the same entity, CA is set to true in Basic Constraints (it should also be marked as critical), key usage is keyCertSign and crlSign (if you are using CRLs), and the Subject Key Identifier (SKI) is the same as the Authority Key Identifier (AKI).

To become your own certificate authority, see *How do you sign a certificate signing request with your certification authority? on Stack Overflow. Then, import your CA into the Trust Store used by the browser.

Steps 2 - 4 are roughly what you do now for a public facing server when you enlist the services of a CA like Startcom or CAcert. Steps 1 and 5 allows you to avoid the third-party authority, and act as your own authority (who better to trust than yourself?).

The next best way to avoid the browser warning is to trust the server's certificate. But some browsers, like Android's default browser, do not let you do it. So it will never work on the platform.

The issue of browsers (and other similar user agents) not trusting self-signed certificates is going to be a big problem in the Internet of Things (IoT). For example, what is going to happen when you connect to your thermostat or refrigerator to program it? The answer is, nothing good as far as the user experience is concerned.

The W3C's WebAppSec Working Group is starting to look at the issue. See, for example, Proposal: Marking HTTP As Non-Secure.


How to create a self-signed certificate with OpenSSL

The commands below and the configuration file create a self-signed certificate (it also shows you how to create a signing request). They differ from other answers in one respect: the DNS names used for the self signed certificate are in the Subject Alternate Name (SAN), and not the Common Name (CN).

The DNS names are placed in the SAN through the configuration file with the line subjectAltName = @alternate_names (there's no way to do it through the command line). Then there's an alternate_names section in the configuration file (you should tune this to suit your taste):

[ 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

It's important to put DNS name in the SAN and not the CN, because both the IETF and the CA/Browser Forums specify the practice. They also specify that DNS names in the CN are deprecated (but not prohibited). If you put a DNS name in the CN, then it must be included in the SAN under the CA/B policies. So you can't avoid using the Subject Alternate Name.

If you don't do put DNS names in the SAN, then the certificate will fail to validate under a browser and other user agents which follow the CA/Browser Forum guidelines.

Related: browsers follow the CA/Browser Forum policies; and not the IETF policies. That's one of the reasons a certificate created with OpenSSL (which generally follows the IETF) sometimes does not validate under a browser (browsers follow the CA/B). They are different standards, they have different issuing policies and different validation requirements.


Create a self signed certificate (notice the addition of -x509 option):

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

Create a signing request (notice the lack of -x509 option):

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

Print a self-signed certificate:

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

Print a signing request:

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

Configuration file (passed via -config option)

[ 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        = [email protected]

# 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

You may need to do the following for Chrome. Otherwise Chrome may complain a Common Name is invalid (ERR_CERT_COMMON_NAME_INVALID). I'm not sure what the relationship is between an IP address in the SAN and a CN in this instance.

# IPv4 localhost
# IP.1       = 127.0.0.1

# IPv6 localhost
# IP.2     = ::1

There are other rules concerning the handling of DNS names in X.509/PKIX certificates. Refer to these documents for the rules:

RFC 6797 and RFC 7469 are listed, because they are more restrictive than the other RFCs and CA/B documents. RFCs 6797 and 7469 do not allow an IP address, either.

Solution 3

As of 2022 with OpenSSL ≥ 1.1.1, the following command serves all your needs, including Subject Alternate Name (SAN):

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:www.example.net,IP:10.0.0.1"

On old systems with OpenSSL ≤ 1.1.0, such as Debian ≤ 9 or CentOS ≤ 7, a longer version of this command needs to be used:

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:www.example.net,IP:10.0.0.1
    ) \
  -subj "/CN=example.com"

Either command creates a certificate that is

  • valid for the (sub)domains example.com and www.example.net (SAN),
  • also valid for the IP address 10.0.0.1 (SAN),
  • relatively strong (as of 2022) and
  • valid for 3650 days (~10 years).

The following files are generated:

  • Private key: example.key
  • Certificate: example.crt

All information is provided at the command line. There is no interactive input that annoys you. There are no config files you have to mess around with. All necessary steps are executed by a single OpenSSL invocation: from private key generation up to the self-signed certificate.


Remark #1: Crypto parameters

Since the certificate is self-signed and needs to be accepted by users manually, it doesn't make sense to use a short expiration or weak cryptography.

In the future, you might want to use more than 4096 bits for the RSA key and a hash algorithm stronger than sha256, but as of 2022 these are sane values. They are sufficiently strong while being supported by all modern browsers.

Remark #2: Parameter "-nodes"

Theoretically you could leave out the -nodes parameter (which means "no DES encryption"), in which case example.key would be encrypted with a password. However, this is almost never useful for a server installation, because you would either have to store the password on the server as well, or you'd have to enter it manually on each reboot.

Remark #3: See also

Solution 4

Here are the options described in @diegows's answer, described in more detail, from the documentation:

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

PKCS#10 certificate request and certificate generating utility.

-x509

this option outputs a self signed certificate instead of a certificate request. This is typically used to generate a test certificate or a self signed root CA.

-newkey arg

this option creates a new certificate request and a new private key. The argument takes one of several forms. rsa:nbits, where nbits is the number of bits, generates an RSA key nbits in size.

-keyout filename

this gives the filename to write the newly created private key to.

-out filename

This specifies the output filename to write to or standard output by default.

-days n

when the -x509 option is being used this specifies the number of days to certify the certificate for. The default is 30 days.

-nodes

if this option is specified then if a private key is created it will not be encrypted.

The documentation is actually more detailed than the above; I just summarized it here.

Solution 5

I can't comment, so I will put this as a separate answer. I found a few issues with the accepted one-liner answer:

  • The one-liner includes a passphrase in the key.
  • The one-liner uses SHA-1 which in many browsers throws warnings in console.

Here is a simplified version that removes the passphrase, ups the security to suppress warnings and includes a suggestion in comments to pass in -subj to remove the full question list:

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

Replace 'localhost' with whatever domain you require. You will need to run the first two commands one by one as OpenSSL will prompt for a passphrase.

To combine the two into a .pem file:

cat server.crt server.key > cert.pem
Share:
2,372,224
michelemarcon
Author by

michelemarcon

Hello, I'm a Java software engineer. I also have some Android and Linux experience.

Updated on March 01, 2022

Comments

  • michelemarcon
    michelemarcon about 2 years

    I'm adding HTTPS support to an embedded Linux device. I have tried to generate a self-signed certificate with these steps:

    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
    

    This works, but I get some errors with, for example, Google Chrome:

    This is probably not the site you are looking for!
    The site's security certificate is not trusted!

    Am I missing something? Is this the correct way to build a self-signed certificate?

    • user1202136
      user1202136 about 12 years
      Self-signed certificates are considered insecure for the Internet. Firefox will treat the site as having an invalid certificate, while Chrome will act as if the connection was plain HTTP. More details: gerv.net/security/self-signed-certs
    • trojanfoe
      trojanfoe about 12 years
      You need to import your CA certificate into your browsers and tell the browsers you trust the certificate -or- get it signed by one of the big money-for-nothing organizations that are already trusted by the browsers -or- ignore the warning and click past it. I like the last option myself.
    • jww
      jww over 9 years
      You should not use the "stock" OpenSSL settings like that. That's because you cannot place DNS names in the Subject Alternate Name (SAN). You need to provide a configuration file with an alternate_names section and pass it with the -config option. Also, placing a DNS name in the Common Name (CN) is deprecated (but not prohibited) by both the IETF and the CA/Browser Forums. Any DNS name in the CN must also be present in the SAN. There's no way to avoid using the SAN. See answer below.
    • GerardJP
      GerardJP almost 7 years
      In addition to @jww 's comment. Per may 2017 Chrome doesn't accept certs w/o (emtpy) SAN's anymore: "The certificate for this site does not contain a Subject Alternative Name extension containing a domain name or IP address."
    • DisappointedByUnaccountableMod
      DisappointedByUnaccountableMod about 6 years
      These days, as long as your webserver is accessible by its FQDN on port 80 over the internet, you can use LetsEncrypt and get free full CA certs (valid for 90 days, renewal can be automated) that won't give any browser warnings/messages. www.letsencrypt.com
    • Yu Jiaao
      Yu Jiaao over 4 years
      The Let's Encrypt site is not .com but .org
  • Cerin
    Cerin over 10 years
    Does this support a wildcard?
  • Diego Woitasen
    Diego Woitasen over 10 years
    Yes, but because is a self-signed certificado, doesn't make any sense usually :)
  • Diego Woitasen
    Diego Woitasen over 10 years
    @coder101 in the current working directory. Files key.pem and cert.pem.
  • Bob Kerns
    Bob Kerns about 10 years
    @diegows -- thanks for this answer. I keep googling it up again, because I never remember that it's part of the 'req' subcommand, not the 'x509' subcommand. And even if I did, I'd have to scratch my head and try a few times to get it right. Thanks for making my day go a bit smoother.
  • Admin
    Admin about 10 years
    For anyone who's interested, here is the documentation, if you want to verify anything yourself.
  • James Mills
    James Mills almost 10 years
    How does signing with a 3rd-party provide more security?
  • Mark
    Mark over 9 years
    If it's a self signed key, it's going to generate browser errors anyway, so this doesn't really matter
  • Maris B.
    Maris B. over 9 years
    @Mark, it matters, because SHA-2 is more secure
  • sinned
    sinned over 9 years
    Opening the certificate in windows after renaming the cert.pem to cert.cer says the fingerprint algorithm still is Sha1, but the signature hash algorithm is sha256.
  • jww
    jww over 9 years
    @Rob - placing a DNS name (like localhost) in the CN is deprecated by both the IETF and CA/B Forums. While its deprecated, its currently not prohibited (that's coming next for the CA/B). All names go in the Subject Alternate Name. If a certificate has a DNS name in the CN, then it must also be present in the SAN. Otherwise, the certificate will fail to validate under browsers and other user agents that follow the CA/B. There's no way to avoid using the SAN.
  • thouliha
    thouliha about 9 years
    Could I use this same cert file for multiple websites on different ip addresses?
  • Alex S
    Alex S almost 9 years
    For anyone else using this in automation, here's all of the common parameters for the subject: -subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=www.example.com"
  • James Selvakumar
    James Selvakumar almost 9 years
    It is not possible to specify the encryption algorithm for your key if you generate the key pair and certificate in one command. If that's a concern, then the key pair should be generated separately: openssl genrsa -aes128 -out server-key.pem
  • Seng Cheong
    Seng Cheong over 8 years
    @jww It would be awesome if you included the options to add a Subject Alternate Name (for DNS names).
  • jww
    jww over 8 years
    @JonathonReinhart - see the answer below. Its a bit long winded, but there's no easy way to do it with OpenSSL because you can't pass a SAN via the command line. It also provides references to the relevant standards.
  • LeonardChallis
    LeonardChallis over 8 years
    Is it possible to use wildcards in the alternate_names section? Particularly sub-sub domains. I have a question referencing this answer here: serverfault.com/questions/711596/…
  • Capaj
    Capaj over 8 years
    I needed a dev certificate for github.com/molnarg/node-http2 and this answer is just the best.
  • 18446744073709551615
    18446744073709551615 over 8 years
    To combine the certificate and the key in a single file: cat server.crt server.key >foo-cert.pem. Works with the example in openssl-1.0.2d/demos/ssl/
  • CamM
    CamM over 8 years
    This answer unexpectedly includes a passphrase in the key - see Mike Ns answer below for an alternative that does not include a passphrase.
  • BrainSlugs83
    BrainSlugs83 over 8 years
    @JamesMills I mean, think about it -- if a shady looking guy with "free candy" written on the side of his van invites you to come inside, you're totally going to think twice and be on guard about it -- but if someone you trust -- like really trust -- is all like, "naw man, he's legit" you're going to be all about that free candy.
  • James Mills
    James Mills over 8 years
    @BrainSlugs83 I think you just totally validated my point entirely :)
  • BrainSlugs83
    BrainSlugs83 over 8 years
    @JamesMills all I saw was your question, didn't see anything else. -- To elaborate: basically it prevents impersonation attacks (i.e. man in the middle, etc.) -- More Info: en.wikipedia.org/wiki/Man-in-the-middle_attack
  • user169771
    user169771 over 8 years
    The cert I generated this way is still using SHA1.
  • Gea-Suan Lin
    Gea-Suan Lin over 8 years
    Remember to use -sha256 to generate SHA-256-based certificate.
  • basickarl
    basickarl about 8 years
    However it may seem confusing for beginners the Create a self signed certificate vs. Create a signing request
  • Diego Woitasen
    Diego Woitasen about 8 years
    I've just replied to his specific question. I think doesn't make sense to add this long security description when the answer was so simple
  • jww
    jww about 8 years
    @diegows - your answer is not complete or correct. The reason it is not correct is discussed in the long post you don't want to read :)
  • akostadinov
    akostadinov almost 8 years
    this will result in: received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message. on client side.
  • Chomeh
    Chomeh over 7 years
    Thanks! I found your post very helpful. FYI I was recently playing with vault and found it insisted on IP.x 127.0.0.1 rather than DNS.x 127... I didn't check if this is in the standard or not.
  • Thiago Pereira
    Thiago Pereira over 7 years
    Tks, works great to create a self signed certificate on FreeBSD 10 OpenLDAP 2.4 with TLS
  • Nathan Jones
    Nathan Jones over 7 years
    The XXX in the original command should be replaced with the 'number of days to certify the certificate for'. The default is 30 days. For example, -days XXX becomes -days 365 if you want your cert to be valid for 365 days. See the docs for more.
  • quikchange
    quikchange over 7 years
    What about the key.pem file?
  • vog
    vog over 7 years
    Being disappointed that all proposed improvements are ignored, I created a new answer that contains all improvements of the comments here: stackoverflow.com/a/41366949/19163
  • Diego Woitasen
    Diego Woitasen over 7 years
    Not ignoring, but a simple question need a simple answer. For a more complete description, you have the documentation :)
  • vog
    vog about 7 years
    There is more improve on @diegows' answer, such as using "-nodes" and "-subj". But since collecting all useful parameters is more the purpose of an anwer than a comment, I summarized these in a separate answer: stackoverflow.com/a/41366949.
  • Robin Zimmermann
    Robin Zimmermann about 7 years
    Thank you @jww. You said, "1. Create your own authority (i.e, become a CA)", then said, "5. Install the CA certificate on the client". If the root key became compromised, a malicious person could sign a cert for any domain with that key, and if they trick you into going to their website, they can now do a man-in-the-middle attack. Is there a way to create the root CA such that it can only sign intermediary CAs and not certificates? Then you can protect your intermediary CA with a name constraint.
  • CGodo
    CGodo almost 7 years
    It worked for me after removing the last parameter -extensions 'v3_req' which was causing an error. Using OpenSSL for windows. Finally, I manage to fix this issue! Thanks.
  • rymo
    rymo almost 7 years
    @Kyopaxa you're right - that parameter is redundant with line 3 of the cnf file; updated.
  • The Red Pea
    The Red Pea almost 7 years
    Thanks for adding the documentation. This IBM link on creating a self-signed certificate using command which seems identical to this answer
  • Andrew Savinykh
    Andrew Savinykh almost 7 years
    Yes, this is very relevant now, five years later. Most of the other answers, as stated, suddenly stopped working. The minimal config given in this answer is very useful, since it would have taken quite some time to figure it out by trial and error.
  • cherouvim
    cherouvim almost 7 years
    Solid way. Thanks. I'd suggest adding -sha256.
  • jmd
    jmd over 6 years
    @Maris : not really more secure here, since it's self-signed !
  • Maris B.
    Maris B. over 6 years
    @jmd - sha256 makes self-signed certificates more secure. And actually self-signed certificates can be more secure (in contrast to CA managed ones, if you do not trust third parties). Rad more here: serverfault.com/questions/363707/…
  • jmd
    jmd over 6 years
    No @Maris. You can consider trusting your self-signed certificate through out-of-band method more secure than accepting one signed by a public CA, but in no case you will use it's signature to trust it, so in no case will the fact that this signature uses sha256 or sha1 have any weight.
  • Phung D. An
    Phung D. An over 6 years
    For windows users, cat command is here => type server.crt server.key > cert.pem
  • Saqib Omer
    Saqib Omer over 6 years
    Works on macOS High Siera and Chrome 58
  • vog
    vog over 6 years
    @DiegoWoitasen I don't see how this answer is simpler than the proposed alternatives. It has fewer command line arguments, for sure, but those missing arguments make everything else more cumbersome than it needs to be. And the proposed expiration of just 365 days is asking for a lot of trouble. stackoverflow.com/a/41366949/19163
  • vog
    vog over 6 years
    You don't need to go through all those steps. You can put everything together in a single, simple command. See: stackoverflow.com/a/41366949/19163
  • Alexandre DuBreuil
    Alexandre DuBreuil over 6 years
    You can now specify the SAN on the command line with -extension 'subjectAltName = DNS:dom.ain, DNS:oth.er' see github.com/openssl/openssl/pull/4986
  • rymo
    rymo over 6 years
    @AlexandreDuBreuil this is good to know. Is that in an available release or still in development?
  • Alexandre DuBreuil
    Alexandre DuBreuil over 6 years
    @rymo it's merged but not released yet, check the issue for info
  • Alex Vasilev
    Alex Vasilev about 6 years
    Getting 'There are issues with the site's certificate chain (net::ERR_CERT_AUTHORITY_INVALID).' in Chrome
  • Jus
    Jus about 6 years
    In the step "Create a self signed certificate", I get the error: unable to find 'distinguished_name' in config problems making Certificate Request 140429517596352:error:0E06D06C:configuration file routines:NCONF_get_string:no value:conf_lib.c:324:group=req name=distinguished_name. Batteries not included?
  • x-yuri
    x-yuri about 6 years
    "World-class encryption * zero authentication = zero security" gerv.net/security/self-signed-certs
  • DJ2
    DJ2 about 6 years
    I'm still not sure how the CN affects the overall setup? I'm attempting to run this as localhost or 127.0.0.1:port# what would be the corresponding CN for something like this.
  • Drakes
    Drakes about 6 years
    @DJ2 I would set BASE_DOMAIN=“localhost”
  • Andrew Henle
    Andrew Henle almost 6 years
    Note that the signature algorithm used on a self-signed certificate is irrelevant in deciding whether it's trustworthy or not. Root CA certs are self-signed. and as of May 2018, there are still many active root CA certificates that are SHA-1 signed. Because it doesn't matter if a certificate trusts itself, nor how that certificate verifies that trust. You either trust the root/self-signed cert for who it says it is, or you don't. See security.stackexchange.com/questions/91913/…
  • declension
    declension over 5 years
    For Linux users you'll need to change that path for the config. e.g. on current Ubuntu /etc/ssl/openssl.conf works
  • mkjeldsen
    mkjeldsen over 5 years
    It looks like the -extension option was released about a month ago in OpenSSL 1.1.1. Ubuntu 18.10 will ship 1.1.0h so many users will still have to wait a long time.
  • Alexandr Zarubkin
    Alexandr Zarubkin over 5 years
    Looks like this option is called -addext now.
  • vog
    vog over 5 years
    For a one-liner that doesn't require you to specify the openssl.cnf location, see: stackoverflow.com/a/41366949/19163
  • Gert van den Berg
    Gert van den Berg over 5 years
    All the arguments except for SANs... @vog's answer covers that as well (and predate this) (This has a more complete "Subject" field filled in though...) (Not a big fan of the one year expiry either)
  • Yuri Pozniak
    Yuri Pozniak over 5 years
    I tried to use the oneliner #2 (modern) on windows in mingw64, and I faced a bug with -subj parameter. ` $ openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout localhost.key -out localhost.crt -subj '/CN=localhost' -addext subjectAltName=DNS:localhost,IP:127.0.0.1 Generating a RSA private key [...] writing new private key to 'localhost.key' ----- name is expected to be in the format /type0=value0/type1=value1/type2=... where characters may be escaped by \. This name is not in that format: 'C:/Program Files/Git/CN=localhost' problems making Certificate Request `
  • Yuri Pozniak
    Yuri Pozniak over 5 years
    I couldn't figure out what exactly was to blame in the arg /CN=localhost expanding to C:/Program Files/Git/CN=localhost , so I just ran the whole command in plain cmd.exe and it worked just fine. Just in case someone is struggling with this one.
  • Franklin Yu
    Franklin Yu over 5 years
    If -newkey rsa:4096 is omitted, OpenSSL defaults to 2048-bit RSA which sounds enough. Also I think -sha256 is the default for 1.1.1 or above.
  • vog
    vog over 5 years
    @FranklinYu Are you sure that rsa:2048 will be enough in 10 years from now? Because that's the validity period. As explained, it doesn't make sense to use short expiration or weak crypto. Most 2048-bit RSA keys have a validity period of 1-3 years at most. Regarding OpenSSL 1.1.1, I'm still leaving sha256 in there, so it's more explicit and obvious to change if you want a stronger hash.
  • rhoerbe
    rhoerbe over 5 years
    Good answer, except the commend that a CA-signature adds more security. The best security is to depend on a public key that you exchange in a secure way, like face to face. PKIX, CA-signatures etc. make this scalable beyond small communites, but actually introduce new attack vectors.
  • Shruggie
    Shruggie about 5 years
    Here's a starter file similar to this answer github.com/bencmbrook/certificate-authority
  • Dave Ferguson
    Dave Ferguson almost 5 years
    If you're using git bash on windows, like @YuriyPozniak, you will get the error he listed where /CN=localhost is being expanded to C:/Progra Files/Git/CN=localhost. If you add an extra /, then the expansion won't occur. //CN=localhost
  • vog
    vog almost 5 years
    @DaveFerguson Isn't the certificate then created for //CN=localhost instead of /CN=localhost? Will proper escaping help here? For example, does replacing /CN=localhost with "/CN=localhost" solve the problem in a clean way?
  • Dave Ferguson
    Dave Ferguson almost 5 years
    @vog I tested using quotes and doesn't work as it still does the path expansion. I also checked the certificate and the subject is correct. Alternatively, you can set an environment variable to disable path expansion (MSYS_NO_PATHCONV=1 openssl <args>). See stackoverflow.com/a/34386471. If you are using the git bash MINGW64 terminal window and you're trying to export the cert to a pfx file, you may also run into the password prompt not showing. Put winpty in front of the command. See omgdebugging.com/2019/03/18/…
  • vog
    vog almost 5 years
    @DaveFerguson My answer already contains a hint to MSYS_NO_PATHCONV. Is this information not prominent enough? How should it be improved?
  • Dave Ferguson
    Dave Ferguson almost 5 years
    @vog Apologies, no disrespect intended. It looks great, actually. I had searched for specific text strings and saw the comment by Yuriy based on the actual error text I was seeing in my terminal. Since the error wasn't listed in the answer directly, I totally missed that section of the answer and focused on the comments instead. Perhaps if you included the error message in the answer text it would help with searches? Also, the double forward slash shortcut is useful too.
  • vog
    vog almost 5 years
    @DaveFerguson I fully agree that the MinGW section is incomplete as it should include the error message that it solves. Would you mind providing the exact error message that you get without MSYS_NO_PATHCONV=1? Thanks!
  • S Meaden
    S Meaden almost 5 years
    For windows file join I use copy /b
  • Joshua Pinter
    Joshua Pinter over 4 years
    1000 +1s for creating a "one-liner" that uses the new required SAN without having to create a long-winded config file with a lot of boilerplate. Well done!
  • Mark Amery
    Mark Amery over 4 years
    -1; this is largely tangential to the question asked, and also does a bad job of making clear where its quotes are from.
  • ThorSummoner
    ThorSummoner over 4 years
    This shows provisioning CA, Server/Client certs signed by the CA, configure them for reading by mysqld on a host with apparmor. It exemplifies a rather useless case of hosting the ca, server, and client on the same machine, and dangerously exposing that ca's authority to the mysqld process. This setup doesn't really make sense other than to test ssl configuration in a test environment. For operating an internal CA, I would recommend the gnuttls toolchain over openssl help.ubuntu.com/community/GnuTLS and having a good understanding of tls before working around the mysqld+apparmor case
  • HackSlash
    HackSlash over 4 years
    This advice about self signed certificates not providing security completely bizarre because all root CA certs are self-signed. You trust those better than ones you signed yourself? Interesting. The reason to use SHA2 instead of SHA1 for self signed certs is that SHA1 is now considered a weak hashing algorithm. Encryption of anonymous messages is still secure, despite lacking authentication. Really depends on your application.
  • gman
    gman over 4 years
    when I use these firefox expectedly complains the cert is self signed but lets me advance to the requested webpage. Chrome on the other hand does not. Any ideas what I need to change?
  • Muhammad Umer
    Muhammad Umer about 4 years
    NET::ERR_CERT_INVALID
  • cautionbug
    cautionbug about 4 years
    @YuriyPozniak @vog @DaveFerguson et al: i encountered pretty much the same problem with the second one-liner. Solution: BOTH the -subj and -addext values need to be wrapped in " " like so: ... -subj "/CN=example.com" -addext "subjectAltName=..."
  • vog
    vog about 4 years
    @cautionbug Thanks! I just edited this into the answer. Is the answer now correct for Windows/MinGW?
  • cautionbug
    cautionbug about 4 years
    @vog Looks great! However, i'm not sure the reference to MSYS_NO_PATHCONV remains necessary with that correction. Maybe replace with notes that arguments with Windows-illegal path/file characters should be enclosed in " "?
  • vog
    vog about 4 years
    @cautionbug Feel free to make a test. I'd also be happy to remove the entire Remark #3: MinGW if the above command (i.e. the second "one-liner") works as-is on Windows.
  • 1_bug
    1_bug about 4 years
    I've tried above solution and it's works for me on every web browser except Firefox. After deep digging I found a solution for Windows users here: serverfault.com/questions/1002185/…
  • cautionbug
    cautionbug about 4 years
    @vog - Mine were generated just fine without the env variable. So i think Remark 3 can go away. :)
  • vog
    vog about 4 years
    @cautionbug Thanks for testing! I just removed the obsolete Remark#3 and renamed Remark#4 to Remark#3.
  • user3605780
    user3605780 about 4 years
    For anyone getting the error: Can't load ./.rnd into RNG running touch ~/.rnd helped for me. github.com/openssl/openssl/issues/7754
  • bArraxas
    bArraxas about 4 years
    Incredible ! It works perfectly if you dont forget to replace "10.0.0.1" by your own local IP. AND restart the PC. It's boring but it's required (thanks windows or chrome) !
  • bajicdusko
    bajicdusko about 4 years
    Although, this process looks complicated, this is exactly what we need for .dev domain, as this domain does not support self-signed certificates and Chrome and Firefox are forcing HSTS. What I did is followed this steps, which is creating CA, creating a certificate and signing it with my CA and at the end trusting my CA in the browser. Thanks.
  • Britton Kerin
    Britton Kerin almost 4 years
    So I went to generate a batch of 40 of these, and it took 5s. Where did it get all the entropy? gpg takes a long time to do similar thing
  • johnrao07
    johnrao07 almost 4 years
    where is the pem file stored in windows?
  • mirageglobe
    mirageglobe over 3 years
    Your common name is wrong. Not firstname/lastname. its your domain cn i.e. www.yoursite.com . see ssl.com/faqs/common-name
  • mirageglobe
    mirageglobe over 3 years
    req part looks wrong. it looks like its pointing back to itself
  • vog
    vog over 3 years
    @JimmyMGLim Do you care to elaborate? Which of the two commands did you try? Did they fail? Did they produce a wrong result? What do you think should be changed in the answer?
  • mirageglobe
    mirageglobe over 3 years
    no problem. there are some documents which also say name (yourname) which is a bit misleading. but common name should be the actual domain. in this sense it would be (your"domain"name) they are trying to say. when running thru with interactive method of creating the certs, it does say cn=domain example. so commonname should be domain
  • mirageglobe
    mirageglobe over 3 years
    [req] represents the config part of the cert request. see switch.ch/pki/manage/request/csr-openssl .. as part of [req] it points to [dn] for example which that section defines the distinguished name. If you really want to define that.. you can do [req] distinguished_name = dn [dn] C = GB O = foo limited CN = foobar.example.com
  • Alex. S.
    Alex. S. over 3 years
    As of Aug-31/2020 I can vouch this works!!! Thanks a lot! I really would like to see a reference that explains in simple terms why this is evolving at such pace. Part of me wonders if it's just because the idea of creating self signed certs is counter productive to the big tech cos. What is going to be needed in 10 or 20 years time? It's madness, and it's a testament of that the amount of activity this kind of questions on openssl generates.
  • Sandrin Joy
    Sandrin Joy over 3 years
    should i replace example.com with my domain?
  • vog
    vog over 3 years
    @SandrinJoy Yes. And www.example.net with your second domain, if you need.
  • mrkiril
    mrkiril over 3 years
  • Hugh Barnard
    Hugh Barnard over 3 years
    Just used this to generate a self-signed to test Firefox Mobile connected to a Mojolicious server. I had to do this cd ~/; openssl rand -writerand .rnd to suppress the rnd error message. Then put the cert into /public, downloaded running as http (since it won't connect as https) and installed. Gives the warning dialogue but connects. I actually needed this because Firefox geolocation refuses under http, Chrome is fine. So, thanks!
  • Alex Filatov
    Alex Filatov over 3 years
  • Roman Plášil
    Roman Plášil about 3 years
    @BrittonKerin from the kernel. GPG is a dinosaur
  • sekrett
    sekrett about 3 years
    I upvoted this answer long time ago but now I realise this is NOT the way to generate a self-signed certificate. You are generating a certificate signed by an unknown authority. This is a different thing. A self-signed certificate you can bypass in Chrome browser, but signed by unknown authority not.
  • Diego Woitasen
    Diego Woitasen about 3 years
    Hi @sekrett not sure if I follow. What do you mean exactly? Because there is no authority in a self-signed cert.. and it's always broken, but it could be good in some scenarios for testing purposes for example.
  • sekrett
    sekrett about 3 years
    Finally I got it. This is a self-signed cert but you need to add extended key usage "Server Authentication" to make it work in Chrome: serverfault.com/questions/571910/…. Try with and without it to see the difference in Chrome.
  • gaazkam
    gaazkam almost 3 years
    This results in Apache warnings: AH01906: 127.0.1.1:443:0 server certificate is a CA certificate (BasicConstraints: CA == TRUE !?)
  • cyclingLinguist
    cyclingLinguist over 2 years
    If you're having trouble remove the backslashes.
  • jpaugh
    jpaugh over 2 years
    vog's answer. Linked, because usernames are neither unique nor immutable. "vog" could change to "scoogie" at any point in time.
  • JohnnyJS
    JohnnyJS about 2 years
    I cannot stress that enough!!!!!!! extendedKeyUsage = serverAuth, clientAuth is what got me the button "Proceed to localhost (unsafe)"
  • JohnnyJS
    JohnnyJS about 2 years
    Maybe some smart fellow would be able to make all of this a nice one-liner...
  • Rony Tesler
    Rony Tesler about 2 years
    @jww which long post? What's not complete and correct in this answer?
  • Daniel Klimuntowski
    Daniel Klimuntowski almost 2 years
    what is the v3.ext file in your last command?
  • JohnnyJS
    JohnnyJS almost 2 years
    Edited the answer. look at point 4.