space monkey internal commit export

[katamari commit: 893e1fc168a8ed977f28e07ee0e4a6a62d3cf129]
This commit is contained in:
JT Olds 2014-01-29 16:31:41 -07:00
parent 2e4eff6035
commit 2717095707
3 changed files with 138 additions and 39 deletions

89
pem.go
View File

@ -7,7 +7,6 @@ package openssl
import "C" import "C"
import ( import (
"encoding/pem"
"errors" "errors"
"io/ioutil" "io/ioutil"
"runtime" "runtime"
@ -51,7 +50,12 @@ func (key *pKey) MarshalPKCS1PrivateKeyPEM() (pem_block []byte,
return nil, errors.New("failed to allocate memory BIO") return nil, errors.New("failed to allocate memory BIO")
} }
defer C.BIO_free(bio) defer C.BIO_free(bio)
if int(C.PEM_write_bio_PrivateKey(bio, key.key, nil, nil, C.int(0), nil, rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
if rsa == nil {
return nil, errors.New("failed getting rsa key")
}
defer C.RSA_free(rsa)
if int(C.PEM_write_bio_RSAPrivateKey(bio, rsa, nil, nil, C.int(0), nil,
nil)) != 1 { nil)) != 1 {
return nil, errors.New("failed dumping private key") return nil, errors.New("failed dumping private key")
} }
@ -60,19 +64,20 @@ func (key *pKey) MarshalPKCS1PrivateKeyPEM() (pem_block []byte,
func (key *pKey) MarshalPKCS1PrivateKeyDER() (der_block []byte, func (key *pKey) MarshalPKCS1PrivateKeyDER() (der_block []byte,
err error) { err error) {
// TODO: i can't decipher how to get a generic PKCS1 Private Key in DER bio := C.BIO_new(C.BIO_s_mem())
// format out of the openssl docs, so until someone who knows better if bio == nil {
// can chastise me for this, we'll do it this way. return nil, errors.New("failed to allocate memory BIO")
pem_block, err := key.MarshalPKCS1PrivateKeyPEM()
if err != nil {
return nil, err
} }
var p *pem.Block defer C.BIO_free(bio)
p, pem_block = pem.Decode(pem_block) rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
if len(pem_block) > 0 || p == nil { if rsa == nil {
return nil, errors.New("something went wrong with PEM generation") return nil, errors.New("failed getting rsa key")
} }
return p.Bytes, nil defer C.RSA_free(rsa)
if int(C.i2d_RSAPrivateKey_bio(bio, rsa)) != 1 {
return nil, errors.New("failed dumping private key der")
}
return ioutil.ReadAll(asAnyBio(bio))
} }
func (key *pKey) MarshalPKIXPublicKeyPEM() (pem_block []byte, func (key *pKey) MarshalPKIXPublicKeyPEM() (pem_block []byte,
@ -82,40 +87,60 @@ func (key *pKey) MarshalPKIXPublicKeyPEM() (pem_block []byte,
return nil, errors.New("failed to allocate memory BIO") return nil, errors.New("failed to allocate memory BIO")
} }
defer C.BIO_free(bio) defer C.BIO_free(bio)
if int(C.PEM_write_bio_PUBKEY(bio, key.key)) != 1 { rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
return nil, errors.New("failed dumping public key") if rsa == nil {
return nil, errors.New("failed getting rsa key")
}
defer C.RSA_free(rsa)
if int(C.PEM_write_bio_RSA_PUBKEY(bio, rsa)) != 1 {
return nil, errors.New("failed dumping public key pem")
} }
return ioutil.ReadAll(asAnyBio(bio)) return ioutil.ReadAll(asAnyBio(bio))
} }
func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte, func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte,
err error) { err error) {
// TODO: i can't decipher how to get a generic PKIX Public Key in DER bio := C.BIO_new(C.BIO_s_mem())
// format out of the openssl docs, so until someone who knows better if bio == nil {
// can chastise me for this, we'll do it this way. return nil, errors.New("failed to allocate memory BIO")
pem_block, err := key.MarshalPKIXPublicKeyPEM()
if err != nil {
return nil, err
} }
var p *pem.Block defer C.BIO_free(bio)
p, pem_block = pem.Decode(pem_block) rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key))
if len(pem_block) > 0 || p == nil { if rsa == nil {
return nil, errors.New("something went wrong with PEM generation") return nil, errors.New("failed getting rsa key")
} }
return p.Bytes, nil defer C.RSA_free(rsa)
if int(C.i2d_RSA_PUBKEY_bio(bio, rsa)) != 1 {
return nil, errors.New("failed dumping public key der")
}
return ioutil.ReadAll(asAnyBio(bio))
} }
// LoadPrivateKey loads a private key from a PEM-encoded block. // LoadPrivateKey loads a private key from a PEM-encoded block.
func LoadPrivateKey(pem_block []byte) (PrivateKey, error) { func LoadPrivateKey(pem_block []byte) (PrivateKey, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]), bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]),
C.int(len(pem_block))) C.int(len(pem_block)))
key := C.PEM_read_bio_PrivateKey(bio, nil, nil, nil) if bio == nil {
C.BIO_free(bio) return nil, errors.New("failed creating bio")
if key == nil {
return nil, errorFromErrorQueue()
} }
defer C.BIO_free(bio)
rsakey := C.PEM_read_bio_RSAPrivateKey(bio, nil, nil, nil)
if rsakey == nil {
return nil, errors.New("failed reading rsa key")
}
defer C.RSA_free(rsakey)
// convert to PKEY
key := C.EVP_PKEY_new()
if key == nil {
return nil, errors.New("failed converting to evp_pkey")
}
if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 {
C.EVP_PKEY_free(key)
return nil, errors.New("failed converting to evp_pkey")
}
p := &pKey{key: key} p := &pKey{key: key}
runtime.SetFinalizer(p, func(p *pKey) { runtime.SetFinalizer(p, func(p *pKey) {
C.EVP_PKEY_free(p.key) C.EVP_PKEY_free(p.key)

76
pem_test.go Normal file
View File

@ -0,0 +1,76 @@
// Copyright (C) 2014 Space Monkey, Inc.
package openssl
import (
"bytes"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/hex"
"io/ioutil"
"testing"
)
func TestMarshal(t *testing.T) {
key, err := LoadPrivateKey(keyBytes)
if err != nil {
t.Fatal(err)
}
cert, err := LoadCertificate(certBytes)
if err != nil {
t.Fatal(err)
}
pem, err := cert.MarshalPEM()
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(pem, certBytes) {
ioutil.WriteFile("generated", pem, 0644)
ioutil.WriteFile("hardcoded", certBytes, 0644)
t.Fatal("invalid cert pem bytes")
}
pem, err = key.MarshalPKCS1PrivateKeyPEM()
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(pem, keyBytes) {
ioutil.WriteFile("generated", pem, 0644)
ioutil.WriteFile("hardcoded", keyBytes, 0644)
t.Fatal("invalid private key pem bytes")
}
tls_cert, err := tls.X509KeyPair(certBytes, keyBytes)
if err != nil {
t.Fatal(err)
}
tls_key, ok := tls_cert.PrivateKey.(*rsa.PrivateKey)
if !ok {
t.Fatal("FASDFASDF")
}
_ = tls_key
der, err := key.MarshalPKCS1PrivateKeyDER()
if err != nil {
t.Fatal(err)
}
tls_der := x509.MarshalPKCS1PrivateKey(tls_key)
if !bytes.Equal(der, tls_der) {
t.Fatal("invalid private key der bytes: %s\n v.s. %s\n", hex.Dump(der), hex.Dump(tls_der))
}
der, err = key.MarshalPKIXPublicKeyDER()
if err != nil {
t.Fatal(err)
}
tls_der, err = x509.MarshalPKIXPublicKey(&tls_key.PublicKey)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(der, tls_der) {
ioutil.WriteFile("generated", []byte(hex.Dump(der)), 0644)
ioutil.WriteFile("hardcoded", []byte(hex.Dump(tls_der)), 0644)
t.Fatal("invalid public key der bytes")
}
}

View File

@ -17,8 +17,7 @@ import (
) )
var ( var (
certBytes = []byte(` certBytes = []byte(`-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDxDCCAqygAwIBAgIVAMcK/0VWQr2O3MNfJCydqR7oVELcMA0GCSqGSIb3DQEB MIIDxDCCAqygAwIBAgIVAMcK/0VWQr2O3MNfJCydqR7oVELcMA0GCSqGSIb3DQEB
BQUAMIGQMUkwRwYDVQQDE0A1NjdjZGRmYzRjOWZiNTYwZTk1M2ZlZjA1N2M0NGFm BQUAMIGQMUkwRwYDVQQDE0A1NjdjZGRmYzRjOWZiNTYwZTk1M2ZlZjA1N2M0NGFm
MDdiYjc4MDIzODIxYTA5NThiY2RmMGMwNzJhOTdiMThhMQswCQYDVQQGEwJVUzEN MDdiYjc4MDIzODIxYTA5NThiY2RmMGMwNzJhOTdiMThhMQswCQYDVQQGEwJVUzEN
@ -42,8 +41,7 @@ sRkg/uxcJf7wC5Y0BLlp1+aPwdmZD87T3a1uQ1Ij93jmHG+2T9U20MklHAePOl0q
yTqdSPnSH1c= yTqdSPnSH1c=
-----END CERTIFICATE----- -----END CERTIFICATE-----
`) `)
keyBytes = []byte(` keyBytes = []byte(`-----BEGIN RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA3X94nDbxbK5a5zS4vEqHLHKpUmxavqRL5oXEqKoAy6nm56rv MIIEpQIBAAKCAQEA3X94nDbxbK5a5zS4vEqHLHKpUmxavqRL5oXEqKoAy6nm56rv
C3e9xySe+DBlxIEV/MWU+RYpzjC99QkerfRP493aleqfhn3ZRS3tyKrQtP2z1Zwg C3e9xySe+DBlxIEV/MWU+RYpzjC99QkerfRP493aleqfhn3ZRS3tyKrQtP2z1Zwg
wYqwcoASOLgqzKvtVYQMT1nJaw6O5fUEWG7BMR/ZX5/kcr8XjTGYjgEmrL1WTZ3G wYqwcoASOLgqzKvtVYQMT1nJaw6O5fUEWG7BMR/ZX5/kcr8XjTGYjgEmrL1WTZ3G
@ -70,11 +68,11 @@ ByGgkUECgYEAmop45kRi974g4MPvyLplcE4syb19ifrHj76gPRBi94Cp8jZosY1T
ucCCa4lOGgPtXJ0Qf1c8yq5vh4yqkQjrgUTkr+CFDGR6y4CxmNDQxEMYIajaIiSY ucCCa4lOGgPtXJ0Qf1c8yq5vh4yqkQjrgUTkr+CFDGR6y4CxmNDQxEMYIajaIiSY
qmgvgyRayemfO2zR0CPgC6wSoGBth+xW6g+WA8y0z76ZSaWpFi8lVM4= qmgvgyRayemfO2zR0CPgC6wSoGBth+xW6g+WA8y0z76ZSaWpFi8lVM4=
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----
`) `)
) )
func NetPipe(t testing.TB) (net.Conn, net.Conn) { func NetPipe(t testing.TB) (net.Conn, net.Conn) {
l, err := net.Listen("tcp", ":0") l, err := net.Listen("tcp", "localhost:0")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -479,7 +477,7 @@ func TestStdlibOpenSSLFullDuplexRenegotiation(t *testing.T) {
func LotsOfConns(t *testing.T, payload_size int64, loops, clients int, func LotsOfConns(t *testing.T, payload_size int64, loops, clients int,
sleep time.Duration, newListener func(net.Listener) net.Listener, sleep time.Duration, newListener func(net.Listener) net.Listener,
newClient func(net.Conn) (net.Conn, error)) { newClient func(net.Conn) (net.Conn, error)) {
tcp_listener, err := net.Listen("tcp", ":0") tcp_listener, err := net.Listen("tcp", "localhost:0")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }