mirror of
https://github.com/FiloSottile/mkcert.git
synced 2025-10-14 17:01:41 +08:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fd504a1868 | ||
![]() |
676d4cdf6b | ||
![]() |
9e258bad93 | ||
![]() |
c3bf865b0c | ||
![]() |
fdd8fe8e17 | ||
![]() |
1e7d221386 | ||
![]() |
5651e29aea |
28
CONTRIBUTING.md
Normal file
28
CONTRIBUTING.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# How to Contribute
|
||||||
|
|
||||||
|
We'd love to accept your patches and contributions to this project. There are
|
||||||
|
just a few small guidelines you need to follow.
|
||||||
|
|
||||||
|
## Contributor License Agreement
|
||||||
|
|
||||||
|
Contributions to this project must be accompanied by a Contributor License
|
||||||
|
Agreement. You (or your employer) retain the copyright to your contribution;
|
||||||
|
this simply gives us permission to use and redistribute your contributions as
|
||||||
|
part of the project. Head over to <https://cla.developers.google.com/> to see
|
||||||
|
your current agreements on file or to sign a new one.
|
||||||
|
|
||||||
|
You generally only need to submit a CLA once, so if you've already submitted one
|
||||||
|
(even if it was for a different project), you probably don't need to do it
|
||||||
|
again.
|
||||||
|
|
||||||
|
## Code reviews
|
||||||
|
|
||||||
|
All submissions, including submissions by project members, require review. We
|
||||||
|
use GitHub pull requests for this purpose. Consult
|
||||||
|
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
||||||
|
information on using pull requests.
|
||||||
|
|
||||||
|
## Community Guidelines
|
||||||
|
|
||||||
|
This project follows [Google's Open Source Community
|
||||||
|
Guidelines](https://opensource.google.com/conduct/).
|
10
README.md
10
README.md
@@ -52,7 +52,13 @@ go get -u github.com/FiloSottile/mkcert
|
|||||||
$(go env GOPATH)/bin/mkcert
|
$(go env GOPATH)/bin/mkcert
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows will be supported next. (PRs welcome!)
|
On Arch Linux you can use your [AUR helper](https://wiki.archlinux.org/index.php/AUR_helpers) to install mkcert from the [PKGBUILD](https://aur.archlinux.org/packages/mkcert-git/).
|
||||||
|
|
||||||
|
```
|
||||||
|
yaourt -S mkcert-git
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows will be supported [soon](https://github.com/FiloSottile/mkcert/pull/46).
|
||||||
|
|
||||||
> **Warning**: the `rootCA-key.pem` file that mkcert automatically generates gives complete power to intercept secure requests from your machine. Do not share it.
|
> **Warning**: the `rootCA-key.pem` file that mkcert automatically generates gives complete power to intercept secure requests from your machine. Do not share it.
|
||||||
|
|
||||||
@@ -62,7 +68,7 @@ Windows will be supported next. (PRs welcome!)
|
|||||||
|
|
||||||
For the certificates to be trusted on mobile devices, you will have to install the root CA. It's the `rootCA.pem` file in the folder printed by `mkcert -CAROOT`.
|
For the certificates to be trusted on mobile devices, you will have to install the root CA. It's the `rootCA.pem` file in the folder printed by `mkcert -CAROOT`.
|
||||||
|
|
||||||
On iOS, you can either email the CA to yourself, or serve it from an HTTP server. After installing it, you must [enable full trust in it](https://support.apple.com/en-nz/HT204477).
|
On iOS, you can either use AirDrop, email the CA to yourself, or serve it from an HTTP server. After installing it, you must [enable full trust in it](https://support.apple.com/en-nz/HT204477). **Note**: earlier versions of mkcert ran into [an iOS bug](https://forums.developer.apple.com/thread/89568), if you can't see the root in "Certificate Trust Settings" you might have to update mkcert and [regenerate the root](https://github.com/FiloSottile/mkcert/issues/47#issuecomment-408724149).
|
||||||
|
|
||||||
For Android, you will have to install the CA and then enable user roots in the development build of your app. See [this StackOverflow answer](https://stackoverflow.com/a/22040887/749014).
|
For Android, you will have to install the CA and then enable user roots in the development build of your app. See [this StackOverflow answer](https://stackoverflow.com/a/22040887/749014).
|
||||||
|
|
||||||
|
22
cert.go
22
cert.go
@@ -7,8 +7,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/sha1"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
@@ -134,17 +136,36 @@ func (m *mkcert) loadCA() {
|
|||||||
func (m *mkcert) newCA() {
|
func (m *mkcert) newCA() {
|
||||||
priv, err := rsa.GenerateKey(rand.Reader, 3072)
|
priv, err := rsa.GenerateKey(rand.Reader, 3072)
|
||||||
fatalIfErr(err, "failed to generate the CA key")
|
fatalIfErr(err, "failed to generate the CA key")
|
||||||
|
pub := priv.PublicKey
|
||||||
|
|
||||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||||
fatalIfErr(err, "failed to generate serial number")
|
fatalIfErr(err, "failed to generate serial number")
|
||||||
|
|
||||||
|
spkiASN1, err := x509.MarshalPKIXPublicKey(&pub)
|
||||||
|
fatalIfErr(err, "failed to encode public key")
|
||||||
|
|
||||||
|
var spki struct {
|
||||||
|
Algorithm pkix.AlgorithmIdentifier
|
||||||
|
SubjectPublicKey asn1.BitString
|
||||||
|
}
|
||||||
|
_, err = asn1.Unmarshal(spkiASN1, &spki)
|
||||||
|
fatalIfErr(err, "failed to decode public key")
|
||||||
|
|
||||||
|
skid := sha1.Sum(spki.SubjectPublicKey.Bytes)
|
||||||
|
|
||||||
tpl := &x509.Certificate{
|
tpl := &x509.Certificate{
|
||||||
SerialNumber: serialNumber,
|
SerialNumber: serialNumber,
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
Organization: []string{"mkcert development CA"},
|
Organization: []string{"mkcert development CA"},
|
||||||
OrganizationalUnit: []string{userAndHostname},
|
OrganizationalUnit: []string{userAndHostname},
|
||||||
|
|
||||||
|
// The CommonName is required by iOS to show the certificate in the
|
||||||
|
// "Certificate Trust Settings" menu.
|
||||||
|
// https://github.com/FiloSottile/mkcert/issues/47
|
||||||
|
CommonName: "mkcert " + userAndHostname,
|
||||||
},
|
},
|
||||||
|
SubjectKeyId: skid[:],
|
||||||
|
|
||||||
NotAfter: time.Now().AddDate(10, 0, 0),
|
NotAfter: time.Now().AddDate(10, 0, 0),
|
||||||
NotBefore: time.Now(),
|
NotBefore: time.Now(),
|
||||||
@@ -156,7 +177,6 @@ func (m *mkcert) newCA() {
|
|||||||
MaxPathLenZero: true,
|
MaxPathLenZero: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub := priv.PublicKey
|
|
||||||
cert, err := x509.CreateCertificate(rand.Reader, tpl, tpl, &pub, priv)
|
cert, err := x509.CreateCertificate(rand.Reader, tpl, tpl, &pub, priv)
|
||||||
fatalIfErr(err, "failed to generate CA certificate")
|
fatalIfErr(err, "failed to generate CA certificate")
|
||||||
|
|
||||||
|
44
main.go
44
main.go
@@ -20,11 +20,33 @@ import (
|
|||||||
"golang.org/x/net/idna"
|
"golang.org/x/net/idna"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const usage = `Usage of mkcert:
|
||||||
|
|
||||||
|
$ mkcert -install
|
||||||
|
Install the local CA in the system trust store.
|
||||||
|
|
||||||
|
$ mkcert example.org
|
||||||
|
Generate "example.org.pem" and "example.org-key.pem".
|
||||||
|
|
||||||
|
$ mkcert example.com myapp.dev localhost 127.0.0.1 ::1
|
||||||
|
Generate "example.com+4.pem" and "example.com+4-key.pem".
|
||||||
|
|
||||||
|
$ mkcert '*.example.com'
|
||||||
|
Generate "_wildcard.example.com.pem" and "_wildcard.example.com-key.pem".
|
||||||
|
|
||||||
|
$ mkcert -uninstall
|
||||||
|
Uninstall the local CA (but do not delete it).
|
||||||
|
|
||||||
|
Change the CA certificate and key storage location by setting $CAROOT,
|
||||||
|
print it with "mkcert -CAROOT".
|
||||||
|
`
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
var installFlag = flag.Bool("install", false, "install the local root CA in the system trust store")
|
var installFlag = flag.Bool("install", false, "install the local root CA in the system trust store")
|
||||||
var uninstallFlag = flag.Bool("uninstall", false, "uninstall the local root CA from the system trust store")
|
var uninstallFlag = flag.Bool("uninstall", false, "uninstall the local root CA from the system trust store")
|
||||||
var carootFlag = flag.Bool("CAROOT", false, "print the CAROOT path")
|
var carootFlag = flag.Bool("CAROOT", false, "print the CAROOT path")
|
||||||
|
flag.Usage = func() { fmt.Fprintf(flag.CommandLine.Output(), usage) }
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *carootFlag {
|
if *carootFlag {
|
||||||
if *installFlag || *uninstallFlag {
|
if *installFlag || *uninstallFlag {
|
||||||
@@ -89,27 +111,7 @@ func (m *mkcert) Run(args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
log.Printf(`
|
log.Printf("\n%s", usage)
|
||||||
Usage:
|
|
||||||
|
|
||||||
$ mkcert -install
|
|
||||||
Install the local CA in the system trust store.
|
|
||||||
|
|
||||||
$ mkcert example.org
|
|
||||||
Generate "example.org.pem" and "example.org-key.pem".
|
|
||||||
|
|
||||||
$ mkcert example.com myapp.dev localhost 127.0.0.1 ::1
|
|
||||||
Generate "example.com+4.pem" and "example.com+4-key.pem".
|
|
||||||
|
|
||||||
$ mkcert '*.example.com'
|
|
||||||
Generate "_wildcard.example.com.pem" and "_wildcard.example.com-key.pem".
|
|
||||||
|
|
||||||
$ mkcert -uninstall
|
|
||||||
Uninstall the local CA (but do not delete it).
|
|
||||||
|
|
||||||
Change the CA certificate and key storage location by setting $CAROOT,
|
|
||||||
print it with "mkcert -CAROOT".
|
|
||||||
`)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -100,13 +100,14 @@ func (m *mkcert) forEachNSSProfile(f func(profile string)) (found int) {
|
|||||||
if stat, err := os.Stat(profile); err != nil || !stat.IsDir() {
|
if stat, err := os.Stat(profile); err != nil || !stat.IsDir() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(filepath.Join(profile, "cert8.db")); !os.IsNotExist(err) {
|
|
||||||
f("dbm:" + profile)
|
|
||||||
found++
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(filepath.Join(profile, "cert9.db")); !os.IsNotExist(err) {
|
if _, err := os.Stat(filepath.Join(profile, "cert9.db")); !os.IsNotExist(err) {
|
||||||
f("sql:" + profile)
|
f("sql:" + profile)
|
||||||
found++
|
found++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(filepath.Join(profile, "cert8.db")); !os.IsNotExist(err) {
|
||||||
|
f("dbm:" + profile)
|
||||||
|
found++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
Reference in New Issue
Block a user