diff --git a/key.go b/key.go index cc17f5fc..8fcc2e90 100644 --- a/key.go +++ b/key.go @@ -19,6 +19,9 @@ package openssl // #include // #include // #include +// #include +// #include +// #include // // int EVP_SignInit_not_a_macro(EVP_MD_CTX *ctx, const EVP_MD *type) { // return EVP_SignInit(ctx, type); @@ -86,6 +89,9 @@ type PrivateKey interface { // MarshalPKCS1PrivateKeyDER converts the private key to DER-encoded PKCS1 // format MarshalPKCS1PrivateKeyDER() (der_block []byte, err error) + + // GetModulus returns private key modulus + GetModulus() (modulus []byte, err error) } type pKey struct { @@ -193,6 +199,22 @@ func (key *pKey) MarshalPKIXPublicKeyPEM() (pem_block []byte, return ioutil.ReadAll(asAnyBio(bio)) } +func (key *pKey) GetModulus() ([]byte, error) { + 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) + + m := C.BN_bn2hex(rsa.n) + if m == nil { + return nil, errors.New("failed to find RSA key modulus") + } + defer C.CRYPTO_free(unsafe.Pointer(m)) + + return ([]byte)(C.GoString(m)), nil +} + func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte, err error) { bio := C.BIO_new(C.BIO_s_mem()) @@ -211,6 +233,20 @@ func (key *pKey) MarshalPKIXPublicKeyDER() (der_block []byte, return ioutil.ReadAll(asAnyBio(bio)) } +// LoadPrivateKeyFromEngine loads a provate key from an OpenSSL ENGINE +func LoadPrivateKeyFromEngine(e *Engine, key_id []byte) (PrivateKey, error) { + key := C.ENGINE_load_private_key(e.e, (*C.char)(unsafe.Pointer(&key_id[0])), nil, nil) + if key == nil { + return nil, errors.New("Could not load private key from engine") + } + + p := &pKey{key: key} + runtime.SetFinalizer(p, func(p *pKey) { + C.EVP_PKEY_free(p.key) + }) + return p, nil +} + // LoadPrivateKeyFromPEM loads a private key from a PEM-encoded block. func LoadPrivateKeyFromPEM(pem_block []byte) (PrivateKey, error) { if len(pem_block) == 0 { diff --git a/key_test.go b/key_test.go index 0af90128..6d5c383f 100644 --- a/key_test.go +++ b/key_test.go @@ -174,3 +174,19 @@ func TestSign(t *testing.T) { t.Fatal(err) } } + +func TestModulus(t *testing.T) { + key, err := LoadPrivateKeyFromPEM(keyBytes) + if err != nil { + t.Fatal(err) + } + modulus, err := key.GetModulus() + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(modulus, keyModulus) { + ioutil.WriteFile("calculated", []byte(hex.Dump(modulus)), 0644) + ioutil.WriteFile("hardcoded", []byte(hex.Dump(keyModulus)), 0644) + t.Fatal("invalid private key modulus bytes") + } +} diff --git a/ssl_test.go b/ssl_test.go index f83225de..4754916e 100644 --- a/ssl_test.go +++ b/ssl_test.go @@ -81,6 +81,8 @@ ucCCa4lOGgPtXJ0Qf1c8yq5vh4yqkQjrgUTkr+CFDGR6y4CxmNDQxEMYIajaIiSY qmgvgyRayemfO2zR0CPgC6wSoGBth+xW6g+WA8y0z76ZSaWpFi8lVM4= -----END RSA PRIVATE KEY----- `) + + keyModulus = []byte(`DD7F789C36F16CAE5AE734B8BC4A872C72A9526C5ABEA44BE685C4A8AA00CBA9E6E7AAEF0B77BDC7249EF83065C48115FCC594F91629CE30BDF5091EADF44FE3DDDA95EA9F867DD9452DEDC8AAD0B4FDB3D59C20C18AB072801238B82ACCABED55840C4F59C96B0E8EE5F504586EC1311FD95F9FE472BF178D31988E0126ACBD564D9DC63C13DBAC04645D1F5EC47C32FF4CFC17A9638BCB148DE68E78193CED8E3CBDC3D08640FEE3702B9E298C902500AD1269F073A3FFABAFC43EFE51E9DAC1917EA5A003ED982500907AB1916389AD1ABFBFB3F0CD16217D8F99A551C673B5849039CBCD1894CA9AF50BDA31BCB292D747AD64423011D2B23A44A0D9F74F`) ) func NetPipe(t testing.TB) (net.Conn, net.Conn) {