From ddf7516723769781258356c0f66ac99a52ced831 Mon Sep 17 00:00:00 2001 From: Tejas Dinkar Date: Sun, 9 Aug 2015 14:35:27 +0530 Subject: [PATCH 1/3] Adding support for Encrypting and Decrypting byte arrays with RSA public or private keys --- key.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/key.go b/key.go index ec6d7805..6cf5fb59 100644 --- a/key.go +++ b/key.go @@ -19,6 +19,7 @@ package openssl // #include // #include // #include +// #include // // int EVP_SignInit_not_a_macro(EVP_MD_CTX *ctx, const EVP_MD *type) { // return EVP_SignInit(ctx, type); @@ -53,7 +54,12 @@ import ( type Method *C.EVP_MD var ( - SHA256_Method Method = C.EVP_sha256() + SHA256_Method Method = C.EVP_sha256() + RSA_PADDING_PKCS1 int = C.RSA_PKCS1_PADDING + RSA_PADDING_SSLV23 int = C.RSA_SSLV23_PADDING + RSA_PADDING_NO int = C.RSA_NO_PADDING + RSA_PADDING_PKCS1_OAEP int = C.RSA_PKCS1_OAEP_PADDING + RSA_PADDING_X931 int = C.RSA_X931_PADDING ) type PublicKey interface { @@ -68,6 +74,12 @@ type PublicKey interface { // format MarshalPKIXPublicKeyDER() (der_block []byte, err error) + // Encrypt a src byte array into dst. Returns the number of bytes encrypted. + // src must be shorter than RSA_SIZE - c where c is a constant based on the padding + // dst must be at least RSA_SIZE + // padding is usually defaulted to openssl.RSA_PADDING_PKCS1 + PublicEncrypt(dst []byte, src []byte, padding int) (int, error) + evpPKey() *C.EVP_PKEY } @@ -84,6 +96,12 @@ type PrivateKey interface { // MarshalPKCS1PrivateKeyDER converts the private key to DER-encoded PKCS1 // format MarshalPKCS1PrivateKeyDER() (der_block []byte, err error) + + // Decrpyt the src byte array into dst. Returns the number of bytes decrypted. + // src must be shorter than RSA_SIZE - c where c is a constant based on the padding + // dst must be at least RSA_SIZE + // padding must be the same as the one used to encrypt the data + PrivateDecrypt(dst []byte, src []byte, padding int) (int, error) } type pKey struct { @@ -335,3 +353,37 @@ func GenerateRSAKey(bits int) (PrivateKey, error) { }) return p, nil } + +func (key *pKey) PublicEncrypt(dst []byte, src []byte, padding int) (int, error) { + rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key)) + if rsa == nil { + return 0, errors.New("failed getting rsa key") + } + defer C.RSA_free(rsa) + + srcArray := (*C.uchar)(unsafe.Pointer(&src[0])) + dstArray := (*C.uchar)(unsafe.Pointer(&dst[0])) + outlen := C.RSA_public_encrypt(C.int(len(src)), srcArray, dstArray, rsa, C.int(padding)) + if outlen > 0 { + return int(outlen), nil + } else { + return int(outlen), errors.New("unable to decrypt") + } +} + +func (key *pKey) PrivateDecrypt(dst []byte, src []byte, padding int) (int, error) { + rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key)) + if rsa == nil { + return 0, errors.New("failed getting rsa key") + } + defer C.RSA_free(rsa) + + srcArray := (*C.uchar)(unsafe.Pointer(&src[0])) + dstArray := (*C.uchar)(unsafe.Pointer(&dst[0])) + outlen := C.RSA_private_decrypt(C.int(len(src)), srcArray, dstArray, rsa, C.int(padding)) + if outlen > 0 { + return int(outlen), nil + } else { + return int(outlen), errors.New("unable to decrypt") + } +} From 54185c87277b488da6023571f2cc6b6cdbb51764 Mon Sep 17 00:00:00 2001 From: Tejas Dinkar Date: Sun, 9 Aug 2015 15:21:47 +0530 Subject: [PATCH 2/3] Adding an RSASize() function to help callers create a minimum sized array --- key.go | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/key.go b/key.go index 6cf5fb59..a6c27490 100644 --- a/key.go +++ b/key.go @@ -74,9 +74,12 @@ type PublicKey interface { // format MarshalPKIXPublicKeyDER() (der_block []byte, err error) + // Get the RSA Size + RSASize() (int, error) + // Encrypt a src byte array into dst. Returns the number of bytes encrypted. - // src must be shorter than RSA_SIZE - c where c is a constant based on the padding - // dst must be at least RSA_SIZE + // src must be shorter than RSASize() - c where c is a constant based on the padding + // dst must be at least RSASize() // padding is usually defaulted to openssl.RSA_PADDING_PKCS1 PublicEncrypt(dst []byte, src []byte, padding int) (int, error) @@ -98,8 +101,8 @@ type PrivateKey interface { MarshalPKCS1PrivateKeyDER() (der_block []byte, err error) // Decrpyt the src byte array into dst. Returns the number of bytes decrypted. - // src must be shorter than RSA_SIZE - c where c is a constant based on the padding - // dst must be at least RSA_SIZE + // src must be shorter than RSASize() - c where c is a constant based on the padding + // dst must be at least RSASize() // padding must be the same as the one used to encrypt the data PrivateDecrypt(dst []byte, src []byte, padding int) (int, error) } @@ -354,6 +357,16 @@ func GenerateRSAKey(bits int) (PrivateKey, error) { return p, nil } +func (key *pKey) RSASize() (int, error) { + rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key)) + if rsa == nil { + return 0, errors.New("failed getting rsa key") + } + defer C.RSA_free(rsa) + + return int(C.RSA_size(rsa)), nil +} + func (key *pKey) PublicEncrypt(dst []byte, src []byte, padding int) (int, error) { rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key)) if rsa == nil { @@ -361,9 +374,7 @@ func (key *pKey) PublicEncrypt(dst []byte, src []byte, padding int) (int, error) } defer C.RSA_free(rsa) - srcArray := (*C.uchar)(unsafe.Pointer(&src[0])) - dstArray := (*C.uchar)(unsafe.Pointer(&dst[0])) - outlen := C.RSA_public_encrypt(C.int(len(src)), srcArray, dstArray, rsa, C.int(padding)) + outlen := C.RSA_public_encrypt(C.int(len(src)), (*C.uchar)(unsafe.Pointer(&src[0])), (*C.uchar)(unsafe.Pointer(&dst[0])), rsa, C.int(padding)) if outlen > 0 { return int(outlen), nil } else { @@ -378,9 +389,7 @@ func (key *pKey) PrivateDecrypt(dst []byte, src []byte, padding int) (int, error } defer C.RSA_free(rsa) - srcArray := (*C.uchar)(unsafe.Pointer(&src[0])) - dstArray := (*C.uchar)(unsafe.Pointer(&dst[0])) - outlen := C.RSA_private_decrypt(C.int(len(src)), srcArray, dstArray, rsa, C.int(padding)) + outlen := C.RSA_private_decrypt(C.int(len(src)), (*C.uchar)(unsafe.Pointer(&src[0])), (*C.uchar)(unsafe.Pointer(&dst[0])), rsa, C.int(padding)) if outlen > 0 { return int(outlen), nil } else { From 25e8f858784c4961d7db93abdef649295f810d62 Mon Sep 17 00:00:00 2001 From: Tejas Dinkar Date: Sun, 9 Aug 2015 15:26:53 +0530 Subject: [PATCH 3/3] Added functions to PrivateSign and PublicVerify --- key.go | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/key.go b/key.go index a6c27490..a095d298 100644 --- a/key.go +++ b/key.go @@ -83,6 +83,12 @@ type PublicKey interface { // padding is usually defaulted to openssl.RSA_PADDING_PKCS1 PublicEncrypt(dst []byte, src []byte, padding int) (int, error) + // Decrypt the src byte array (signature) into dst. Returns the number of bytes decrypted. + // src must be shorter than RSASize() - c where c is a constant based on the padding + // dst must be at least RSASize() + // padding must be the same as the one used to encrypt the data + PublicVerify(dst []byte, src []byte, padding int) (int, error) + evpPKey() *C.EVP_PKEY } @@ -100,11 +106,17 @@ type PrivateKey interface { // format MarshalPKCS1PrivateKeyDER() (der_block []byte, err error) - // Decrpyt the src byte array into dst. Returns the number of bytes decrypted. + // Decrypt the src byte array into dst. Returns the number of bytes decrypted. // src must be shorter than RSASize() - c where c is a constant based on the padding // dst must be at least RSASize() // padding must be the same as the one used to encrypt the data PrivateDecrypt(dst []byte, src []byte, padding int) (int, error) + + // Encrypt a src byte array (signature) into dst. Returns the number of bytes encrypted. + // src must be shorter than RSASize() - c where c is a constant based on the padding + // dst must be at least RSASize() + // padding is usually defaulted to openssl.RSA_PADDING_PKCS1 + PrivateSign(dst []byte, src []byte, padding int) (int, error) } type pKey struct { @@ -396,3 +408,33 @@ func (key *pKey) PrivateDecrypt(dst []byte, src []byte, padding int) (int, error return int(outlen), errors.New("unable to decrypt") } } + +func (key *pKey) PublicVerify(dst []byte, src []byte, padding int) (int, error) { + rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key)) + if rsa == nil { + return 0, errors.New("failed getting rsa key") + } + defer C.RSA_free(rsa) + + outlen := C.RSA_public_decrypt(C.int(len(src)), (*C.uchar)(unsafe.Pointer(&src[0])), (*C.uchar)(unsafe.Pointer(&dst[0])), rsa, C.int(padding)) + if outlen > 0 { + return int(outlen), nil + } else { + return int(outlen), errors.New("unable to decrypt") + } +} + +func (key *pKey) PrivateSign(dst []byte, src []byte, padding int) (int, error) { + rsa := (*C.RSA)(C.EVP_PKEY_get1_RSA(key.key)) + if rsa == nil { + return 0, errors.New("failed getting rsa key") + } + defer C.RSA_free(rsa) + + outlen := C.RSA_private_encrypt(C.int(len(src)), (*C.uchar)(unsafe.Pointer(&src[0])), (*C.uchar)(unsafe.Pointer(&dst[0])), rsa, C.int(padding)) + if outlen > 0 { + return int(outlen), nil + } else { + return int(outlen), errors.New("unable to decrypt") + } +}