Updates certificate signing code
This seems to have fixed the SEC_ERROR_REUSED_ISSUER_AND_SERIAL error I was getting in firefox. I have taken the code from the goproxy project. https://github.com/elazarl/goproxy/issues/311
This commit is contained in:
parent
bdb2d4db79
commit
aa1517a820
1 changed files with 42 additions and 15 deletions
57
signer.go
57
signer.go
|
@ -36,8 +36,11 @@ https://github.com/elazarl/goproxy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
@ -45,7 +48,9 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -56,20 +61,24 @@ import (
|
||||||
counterecryptor.go
|
counterecryptor.go
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type counterEncryptorRand struct {
|
type CounterEncryptorRand struct {
|
||||||
cipher cipher.Block
|
cipher cipher.Block
|
||||||
counter []byte
|
counter []byte
|
||||||
rand []byte
|
rand []byte
|
||||||
ix int
|
ix int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCounterEncryptorRandFromKey(key interface{}, seed []byte) (r counterEncryptorRand, err error) {
|
func NewCounterEncryptorRandFromKey(key interface{}, seed []byte) (r CounterEncryptorRand, err error) {
|
||||||
var keyBytes []byte
|
var keyBytes []byte
|
||||||
switch key := key.(type) {
|
switch key := key.(type) {
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
keyBytes = x509.MarshalPKCS1PrivateKey(key)
|
keyBytes = x509.MarshalPKCS1PrivateKey(key)
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
if keyBytes, err = x509.MarshalECPrivateKey(key); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
err = errors.New("only RSA keys supported")
|
err = errors.New("only RSA and ECDSA keys supported")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
|
@ -85,14 +94,14 @@ func newCounterEncryptorRandFromKey(key interface{}, seed []byte) (r counterEncr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *counterEncryptorRand) Seed(b []byte) {
|
func (c *CounterEncryptorRand) Seed(b []byte) {
|
||||||
if len(b) != len(c.counter) {
|
if len(b) != len(c.counter) {
|
||||||
panic("SetCounter: wrong counter size")
|
panic("SetCounter: wrong counter size")
|
||||||
}
|
}
|
||||||
copy(c.counter, b)
|
copy(c.counter, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *counterEncryptorRand) refill() {
|
func (c *CounterEncryptorRand) refill() {
|
||||||
c.cipher.Encrypt(c.rand, c.counter)
|
c.cipher.Encrypt(c.rand, c.counter)
|
||||||
for i := 0; i < len(c.counter); i++ {
|
for i := 0; i < len(c.counter); i++ {
|
||||||
if c.counter[i]++; c.counter[i] != 0 {
|
if c.counter[i]++; c.counter[i] != 0 {
|
||||||
|
@ -102,7 +111,7 @@ func (c *counterEncryptorRand) refill() {
|
||||||
c.ix = 0
|
c.ix = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *counterEncryptorRand) Read(b []byte) (n int, err error) {
|
func (c *CounterEncryptorRand) Read(b []byte) (n int, err error) {
|
||||||
if c.ix == len(c.rand) {
|
if c.ix == len(c.rand) {
|
||||||
c.refill()
|
c.refill()
|
||||||
}
|
}
|
||||||
|
@ -149,9 +158,8 @@ func signHost(ca tls.Certificate, hosts []string) (cert tls.Certificate, err err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
hash := hashSorted(append(hosts, goproxySignerVersion, ":"+runtime.Version()))
|
|
||||||
serial := new(big.Int)
|
serial := big.NewInt(rand.Int63())
|
||||||
serial.SetBytes(hash)
|
|
||||||
template := x509.Certificate{
|
template := x509.Certificate{
|
||||||
// TODO(elazar): instead of this ugly hack, just encode the certificate and hash the binary form.
|
// TODO(elazar): instead of this ugly hack, just encode the certificate and hash the binary form.
|
||||||
SerialNumber: serial,
|
SerialNumber: serial,
|
||||||
|
@ -171,18 +179,32 @@ func signHost(ca tls.Certificate, hosts []string) (cert tls.Certificate, err err
|
||||||
template.IPAddresses = append(template.IPAddresses, ip)
|
template.IPAddresses = append(template.IPAddresses, ip)
|
||||||
} else {
|
} else {
|
||||||
template.DNSNames = append(template.DNSNames, h)
|
template.DNSNames = append(template.DNSNames, h)
|
||||||
|
template.Subject.CommonName = h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var csprng counterEncryptorRand
|
|
||||||
if csprng, err = newCounterEncryptorRandFromKey(ca.PrivateKey, hash); err != nil {
|
hash := hashSorted(append(hosts, goproxySignerVersion, ":"+runtime.Version()))
|
||||||
|
var csprng CounterEncryptorRand
|
||||||
|
if csprng, err = NewCounterEncryptorRandFromKey(ca.PrivateKey, hash); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var certpriv *rsa.PrivateKey
|
|
||||||
if certpriv, err = rsa.GenerateKey(&csprng, 1024); err != nil {
|
var certpriv crypto.Signer
|
||||||
return
|
switch ca.PrivateKey.(type) {
|
||||||
|
case *rsa.PrivateKey:
|
||||||
|
if certpriv, err = rsa.GenerateKey(&csprng, 2048); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
if certpriv, err = ecdsa.GenerateKey(elliptic.P256(), &csprng); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("unsupported key type %T", ca.PrivateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
var derBytes []byte
|
var derBytes []byte
|
||||||
if derBytes, err = x509.CreateCertificate(&csprng, &template, x509ca, &certpriv.PublicKey, ca.PrivateKey); err != nil {
|
if derBytes, err = x509.CreateCertificate(&csprng, &template, x509ca, certpriv.Public(), ca.PrivateKey); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return tls.Certificate{
|
return tls.Certificate{
|
||||||
|
@ -190,3 +212,8 @@ func signHost(ca tls.Certificate, hosts []string) (cert tls.Certificate, err err
|
||||||
PrivateKey: certpriv,
|
PrivateKey: certpriv,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Avoid deterministic random numbers
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue