x509 Go package - ParsePKIXPublicKey is to DER or PEM? - go

I'm trying to get an object of rsa.PublicKey and I made these steps:
----BEGIN RSA PUBLIC KEY----
....
----END RSA PUBLIC KEY----
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
)
func main() {
key, err := ioutil.ReadFile("./new_public.pem")
if err != nil {
fmt.Println(err.Error())
}
block, _ := pem.Decode([]byte(key))
if block == nil {
fmt.Println("unable to decode publicKey to request")
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic("failed to parse RSA encoded public key" + err.Error())
}
switch pub := pub.(type) {
case *rsa.PublicKey:
fmt.Println("pub is of type RSA:", pub)
default:
panic("error")
}
}
After this, when I try to x509.ParsePKIXPublicKey(block.Bytes) I get an error:
panic: failed to parse RSA encoded public keyasn1:
structure error: tags don't match (16 vs {class:0 tag:2 length:129 isCompound:false})
{
optional:false
explicit:false
application:false
private:false
defaultValue:<nil> tag:<nil>
stringType:0
timeType:0
set:false
omitEmpty:false
} AlgorithmIdentifier #3
So, I read some blogs and documentations about DER and PEM formats, and they are differents ways to encode an certificate, basicaly one use base64 and other is just bytes.
In x509's package of Golang, the x509.ParsePKIXPublicKey says:
ParsePKIXPublicKey parses a DER-encoded public key. These values are typically found in PEM blocks with "BEGIN PUBLIC KEY"
And, in the example of this function use the pem.Decode(). I'm very confused about this because this should use pem.Decode or something like der.Decode() ?
Also, what's the real difference between x509.ParsePKCS1PublicKey() and x509.ParsePKIXPublicKey() ? Both do the same job to get a rsa.PublicKey ?

The issue here is understanding the difference between x509.ParsePKCS1PublicKey (PKCS#1) and x509.ParsePKIXPublicKey (PKCS#8).
Usually when the PEM header has the type as RSA PUBLIC KEY, it is referring to a PKCS#1 encoded RSA public key, which is defined in RFC 8017 (PKCS#1) as:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
You haven't actually provided the body of your public key (it would be safe to do so), but it is a fair assumption that, if decoding the key using x509.ParsePKIXPublicKey failed, your key is likely in the above format (x509.ParsePKIXPublicKey uses PKCS#8 encoding).
If this is the case, you should be able to get an rsa.PublicKey from the file using the following code (don't forget to add the error handling):
rawPem, _ := ioutil.ReadFile("./public.key")
pemBlock, _ := pem.Decode(rawPem)
publicKey, _ := x509.ParsePKCS1PublicKey(pemBlock.Bytes)
If this doesn't solve your problem, try pasting the key you have into this site to see what ASN.1 structure it uses. For reference, the key I used to test this is included here:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEApW1W9dnfdFF7FHrq6HPveR/9T+nM70yO7QOGytR0j/chMBJcJBjG
hJOuKPFbkVyS+BE/4M8CojLgvz4ex82Re0sFa5TqnoWvuP5P4vktR6M5W53sTW3y
gUnfF/oHcEmARQ1xKZdgVnlIfrdbpjecPyLi1Ng4HmhEfCFUOW64koxpb4XeH5O5
q+vc/731ExVOYBU8Sl6kPdjpJuVjS3DHKAVgfVEhscXd3JDjDuMDT3w1IYNb5c2s
wHE55q4Jnc1cr42jdynnkXzmuOGo2C6yD95kbBDLp7wSiBxaMA8gbRkzWJ99T+6l
KsKG2zfndMF3jZW1v1wWiEbYRN07qbN0NQIDAQAB
-----END RSA PUBLIC KEY-----

Here you go.
https://golang.org/src/crypto/tls/generate_cert.go
You have to generate the certificates using the code above.
Like this:
./generate_cert --host="source:destination" -rsa-bits 1024
openssl pkcs8 -topk8 -nocrypt -in key.pem -out privatekey.pcks8
openssl x509 -pubkey -noout -in cert.pem > publickey.pem
This should solve the issue for you and give you the files you need.

Related

How to get a string out of x509 certificate public key in go?

If I have an *x509.Certificate object, how can I extract the public key base64 string representation out of it?
NOTE: Jump to #3 if you already have the x509.Certificate object.
You would need to do the following:
Decode the PEM with pem.Decode().
block, _ := pem.Decode([]byte(certPEM))
Parse the certificate with x509.ParseCertificate().
cert, _ := x509.ParseCertificate(block.Bytes)
Marshal the Public key with x509.MarshalPKIXPublicKey().
publicKeyDer, _ := x509.MarshalPKIXPublicKey(cert.PublicKey)
Encode it in a PEM encoded structure with pem.EncodeToMemory().
publicKeyBlock := pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyDer,
}
publicKeyPem := string(pem.EncodeToMemory(&publicKeyBlock))
Run it on Go Playground
You can confirm the result if you copy the certificate in the example to a file cert.pem with the command:
openssl x509 -inform pem -in cert.pem -pubkey -noout
You should get the same result!

Substitute for load_pem_private_key() in golang

I have this code in python
privateKey = appAuth["privateKey"]
passphrase = appAuth["passphrase"]
from cryptography.hazmat.primitives.serialization import load_pem_private_key
key = load_pem_private_key(
data=privateKey.encode('utf8'),
password=passphrase.encode('utf8'),
backend=default_backend(),)
I want to replicate this in golang.
Basically I have this:-
"appAuth": {
"publicKeyID": "2qwqckds",
"privateKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0AeQwwDgQIkkci4MFCUtsCAggA\nMBQGCCqGSIb3DQMHBAjyW3BUgbqg9ASCBMjEpz/mhgRXFKkFpSL4SAq7YLxYzO7H\nYfbisbcsrN4C1wAiXpT4FMBuGnHzRrm/slu+DnTdbsKrg2SxiyW3Zy5FtBfYGPHF\nYim4It2lPywMHHS62b2qXdIicW4pfst/eqeisLpl0bBTR7UYbxr6vpsVFKrGkjEI\n8+VtADGgm6ORH975NBZiLrCEO2aLOfeXlQrdWHcNEB46emvoasBKRZ0bUTxUqKN9\negGPprpfEb7yp0UoJZayYpxcZOSEuM42jXiGELQ9qM7xeADlTP5rbw2d6r/Hbr67\nvyDk2fydvRra4XlbDgeKfiD71OaetoyF8o07Zo4VJegdZnHYW7BW2kXuD5uCiNYI\nWN3l9TpX8i6FU1i++NidH80t5cHAHlhBc2v0if5g8TlmRDarOo6pX8d2KLV98V7F\n7iWmS9vHtyZZvIgaWDchQ+fVQ2ZS6KCRGnGipxkmGyDXnPcx60YPiN9NxCmKs0ji\n8e7xtM+QXzYPWF/rUQh/YmISYGoktOj2XMxXmpNXdpcHFIWEbuW0LuWhV++4WrnO\nly9Vc3PwnHi5KE+IzgoOtgPkxDkr664fd5H0DD3RD1ytWuMW0rtKMr8jx/vRUkzM\n+yzGo0UMe4XW0M0Xcrpq+o+0NBwa05xGA6vlrerMuLcsYG3MexdBkuVMammpmxdM\ntQ+Ch65ikggn9Er2LbwJyddw7bUaIox0hXPUaiAyICY77D7m4SEsBfMFjy420UoR\numz1+ss4edJ0ago0FumG3QaUJzTGUfCHd/johD3AkYAQsFvwiCkMcL2wQEcYDx4x\nx8OCdM1rTn61sQOHHYH4fN4V8TAEbhG57kSzz/GLBlIu84m7zew+NN3pTTw5oU+V\nVHFyBj1eW9ywtING1oEnbKXIdzSs4dWF7zwlzDUfbS5GY6Crm7vhre6pnZY0zs3O\n+MzcGe0AHPwRPOtR4gUiuW5tbBhLM9Nd8xFdS29QUnydKDpSbhySJgCPcYkTtbSG\nsQZMAK7d/Dv178Qta5a+oO0XMh7I4qZ6tuBlGH06QEUh2NJrfzp42hUS0zd9XIZ5\nStD/R9aTSLTr0ljfzrgs/brGj9S0eSHuxV/4teTYapmZoO+G3G7SfViSRn+IdDdK\nOLa5sLeOu/KCdH0mIyVDupmJKt0adAza3S4Wp719HZVrgOOJc4Ni9GXPiPR5Qxv5\nG+/oUIrBxvBpK4gB6Fzr1iRz51FmvukURdeHVDJfbNyEvFWyQ6w5ZXrSbWnD73WB\nk7/J4N2gLKYVYagI/J9GZ4q/cfM5w+JztdqeBXOKa7fyEBE3iEv5hKs/C7lvxuQs\no0yrqTok0GnrlSGq4R0ve/t6eQ4nyWLM1yMxhl/JMGw7QFq7bhfeAhwVcQB7f1eT\n/krRppgbBwkGHaES47LkoBV9AyZlRIymFaF128SePSSa1YgIaivxghcopdqC3HD1\n/NSFA9zvxXv54Neqv9sO2Mc2PHaiOq3RPQbP4zPV7CD8bBSUwztLNAJJC99OeNah\n1nyvS69JvysuM7Mxgv3e8VK4+hQ+I1uMwL8UlfCJZ+ejHwpLX26kc7NfKP/NWzm7\n6JCsEbbtoR7OWnVgXf0lkIlJPcs86HPoX1DzlzVUQsAtKLpnhxLBBfDH5NwVtolM\nn74=\n-----END ENCRYPTED PRIVATE KEY-----\n",
"passphrase": "2788518b2900d77fafc71dbf4f764927"
}
In golang, I have tried this so far:-
block, _ := pem.Decode([]byte(privateKey)) \\ privateKey is a string
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
But it doesn't work.
Please Help.
To decrypt encrypted pkcs8 key (an example of such key is mentioned in the question) in go
there is an awesome library https://github.com/youmark/pkcs8/.
import "github.com/youmark/pkcs8"
block, _ := pem.Decode([]byte(config.BoxAppSetting.AppAuth.PrivateKey))
decryptedPrivateKey, err := pkcs8.ParsePKCS8PrivateKey(block.Bytes, []byte(config.BoxAppSetting.AppAuth.PassPhrase))

How to generate correct RSA key for signing JWT?

I'm using this example, however it is slightly outdated. So, for, example SignedString(key), I guess, receives *rsa.PublicKey instead of []byte in case of RS256 signing method. I generated my private key using
openssl genrsa -out key.rsa 1024
And now trying to parse it:
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
)
func main() {
pem := []byte(`-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCycI9LZT8qM/zCGH0CNxAi7gy7w1YjqZN1N8yFfbmv9toVC82S
bZDv8NVYVlFNhUbtUFg77TYhHmyPpr4hKqvPrVc0rqVFe4ggQYdXovDgLZhO1MxB
i4vw9tLRlAK8TYNFqaFiX6lFgRp8trd01GFhkBJMzZCMmBQFkcEgWqT6MQIDAQAB
AoGBAKSru5GYnfIUh+2XK8YfioSxqo6cdaHznGFQXS3UGMiKxjcl7VB0TI0hc8FR
5zXjCNF4k/S5tHpb2VO4TT3OYz55/JEOGAXvIMW2UYtL4TwR3+46TRJ95KKowq+c
3JndjmGjUbvWawtbNklkmgoEkLI8wYu9yss9293GBnff14ABAkEA1scxu0svrIZ1
R5YmpXOfrtGwsjbdowGNxZTedWlbJukBSNPSIpuUvkzF2PXlPBS80p5yxbYlp1gg
UhsfXWJwIQJBANSv7lEuHV0QnVVoYVtNijwEHIi7iG7xu7hDQ7bK/kwWV6wqnvfP
PZopZPDXCRlnxbubo0/RJz4LsaJflDJKiBECQC/3FFgrll4FOTPfiInypHq6QafL
MPwyYKL7eCLogH7UEoFdLNSlwjYtlxG4+JTOXMz8rc0RvJ7+w1kSzZJhZYECQHMU
DhqWnQSx7K89nw/L0LPQda/16Eg/O5bjrkvFYfrBTAa3uPPUijxTkW5Oq3m3kGGG
QML7JASKRz7YAFOFyEECQQCUBNONRYMMzzr4llGOcKISXJtewlOPTHGP++OiHWMB
rPzZDyi5ONNgySF8t/QnJMTRpRQ5axi0UhojL/OzUt/w
-----END RSA PRIVATE KEY-----`)
key, err := jwt.ParseRSAPublicKeyFromPEM(pem)
fmt.Println(key, err)
}
But I get asn1: structure error: tags don't match (16 vs {class:0 tag:2 length:1 isCompound:false}) {optional:false explicit:false application:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} tbsCertificate #2 in response.
Is my key generating command somehow wrong? What should I read to be able to debug this? What asn1 has to do with it? Key has some particular syntax?
You are passing a RSA PRIVATE KEY but calling jwt.ParseRSAPublicKeyFromPEM. You should be calling jwt.ParseRSAPrivateKeyFromPEM instead.

How to store ECDSA private key in Go

I am using the ecdsa.GenerateKey method to generate a private/public key pair in Go. I would like to store the private key in a file on the users computer, and load it whenever the program starts. There is a method elliptic.Marshal that marshals the public key, but nothing for the private key. Should I simply roll my own, or is there a recommended way to store the private key?
Here is a code sample that demonstrates encoding and decoding of keys in Go. It helps to know that you need to connect couple of steps. Crypto algorithm is the fist step, in this case ECDSA key. Then you need standard encoding, x509 is most commontly used standard. Finally you need a file format, PEM is again commonly used one. This is currently most commonly used combination, but feel free to substitute any other algoriths or encoding.
func encode(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey) (string, string) {
x509Encoded, _ := x509.MarshalECPrivateKey(privateKey)
pemEncoded := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509Encoded})
x509EncodedPub, _ := x509.MarshalPKIXPublicKey(publicKey)
pemEncodedPub := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: x509EncodedPub})
return string(pemEncoded), string(pemEncodedPub)
}
func decode(pemEncoded string, pemEncodedPub string) (*ecdsa.PrivateKey, *ecdsa.PublicKey) {
block, _ := pem.Decode([]byte(pemEncoded))
x509Encoded := block.Bytes
privateKey, _ := x509.ParseECPrivateKey(x509Encoded)
blockPub, _ := pem.Decode([]byte(pemEncodedPub))
x509EncodedPub := blockPub.Bytes
genericPublicKey, _ := x509.ParsePKIXPublicKey(x509EncodedPub)
publicKey := genericPublicKey.(*ecdsa.PublicKey)
return privateKey, publicKey
}
func test() {
privateKey, _ := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
publicKey := &privateKey.PublicKey
encPriv, encPub := encode(privateKey, publicKey)
fmt.Println(encPriv)
fmt.Println(encPub)
priv2, pub2 := decode(encPriv, encPub)
if !reflect.DeepEqual(privateKey, priv2) {
fmt.Println("Private keys do not match.")
}
if !reflect.DeepEqual(publicKey, pub2) {
fmt.Println("Public keys do not match.")
}
}
I believe the standard format for those keys is to use the X.509 ASN.1 DER representation. See http://golang.org/pkg/crypto/x509/#MarshalECPrivateKey and http://golang.org/pkg/crypto/x509/#ParseECPrivateKey.
I adapted a really quick and dirty way to do it, as suggested by one of the geth team in late '15 in my library https://github.com/DaveAppleton/ether_go
it is a far simpler solution (but puts keys in plain sight)

Encrypt message with RSA private key (as in OpenSSL's RSA_private_encrypt)

I'm trying to implement Chef API client in Go, but stuck trying to create correct request header RSA signature. According to documentation:
A canonical header is signed with the private key used by the client machine from which the request is sent, and is also encoded using Base64.
The following ruby call to OpenSSL::PKey::RSA.private_encrypt() can be found in mixlib-authentication gem code, it uses OpenSSL bindings, private_encrypt() method calls RSA_private_encrypt openssl function.
Unfortunately, I cannot find matching function in Go's standard library; crypto/rsa looks close, but it only implements conventional cryptography methods: encryption with public key, hash signing with private key. OpenSSL's RSA_private_encrypt does the opposite: it encrypts (small) message with private key (akin to creating a signature from message hash).
This "signing" can also be achieved with this command:
openssl rsautl -sign -inkey path/to/private/key.pem \
-in file/to/encrypt -out encrypted/output
Are there any native Go libraries to achieve the same result as OpenSSL's RSA_private_encrypt, or the only way is using Cgo to call this function from OpenSSL library? Maybe I'm missing something. My idea was implementing the client without any non-go dependencies.
I'm a Go newbie, so I'm not sure I can dive into crypto/rsa module sources.
Found the similar question, but the answer to use SignPKCS1v15 is obviously wrong (this function encrypts message's hash, not the message itself).
With great help of the golang community, the solution was found:
Original code posted at http://play.golang.org/p/jrqN2KnUEM by Alex (see mailing list).
I've added input block size check as specified in Section 8 of rfc2313: http://play.golang.org/p/dGTl9siO8E
Here's the code:
package main
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"math/big"
"os/exec"
)
var (
ErrInputSize = errors.New("input size too large")
ErrEncryption = errors.New("encryption error")
)
func PrivateEncrypt(priv *rsa.PrivateKey, data []byte) (enc []byte, err error) {
k := (priv.N.BitLen() + 7) / 8
tLen := len(data)
// rfc2313, section 8:
// The length of the data D shall not be more than k-11 octets
if tLen > k-11 {
err = ErrInputSize
return
}
em := make([]byte, k)
em[1] = 1
for i := 2; i < k-tLen-1; i++ {
em[i] = 0xff
}
copy(em[k-tLen:k], data)
c := new(big.Int).SetBytes(em)
if c.Cmp(priv.N) > 0 {
err = ErrEncryption
return
}
var m *big.Int
var ir *big.Int
if priv.Precomputed.Dp == nil {
m = new(big.Int).Exp(c, priv.D, priv.N)
} else {
// We have the precalculated values needed for the CRT.
m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
m.Sub(m, m2)
if m.Sign() < 0 {
m.Add(m, priv.Primes[0])
}
m.Mul(m, priv.Precomputed.Qinv)
m.Mod(m, priv.Primes[0])
m.Mul(m, priv.Primes[1])
m.Add(m, m2)
for i, values := range priv.Precomputed.CRTValues {
prime := priv.Primes[2+i]
m2.Exp(c, values.Exp, prime)
m2.Sub(m2, m)
m2.Mul(m2, values.Coeff)
m2.Mod(m2, prime)
if m2.Sign() < 0 {
m2.Add(m2, prime)
}
m2.Mul(m2, values.R)
m.Add(m, m2)
}
}
if ir != nil {
// Unblind.
m.Mul(m, ir)
m.Mod(m, priv.N)
}
enc = m.Bytes()
return
}
func main() {
// o is output from openssl
o, _ := exec.Command("openssl", "rsautl", "-sign", "-inkey", "t.key", "-in", "in.txt").Output()
// t.key is private keyfile
// in.txt is what to encode
kt, _ := ioutil.ReadFile("t.key")
e, _ := ioutil.ReadFile("in.txt")
block, _ := pem.Decode(kt)
privkey, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
encData, _ := PrivateEncrypt(privkey, e)
fmt.Println(encData)
fmt.Println(o)
fmt.Println(string(o) == string(encData))
}
Update: we can expect to have a native support for this kind of signing in Go 1.3, see the appropriate commit.
Since go 1.3, you can easily do this using SignPKCS1v15
rsa.SignPKCS1v15(nil, priv, crypto.Hash(0), signedData)
refer: https://groups.google.com/forum/#!topic/Golang-Nuts/Vocj33WNhJQ
I stuck on this question for a while.
Eventually, I soleved that with the code here:
https://github.com/bitmartexchange/bitmart-go-api/blob/master/bm_client.go
// Sign secret with rsa with PKCS 1.5 as the padding algorithm
// The result should be exactly same as "openssl rsautl -sign -inkey "YOUR_RSA_PRIVATE_KEY" -in "YOUR_PLAIN_TEXT""
signer, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivateKey.(*rsa.PrivateKey), crypto.Hash(0), []byte(message))
Welcome to the joys of openssl... That is an incredibly poorly named function. If you poke around in the ruby code it's calling this openssl function
http://www.openssl.org/docs/crypto/RSA_private_encrypt.html
Reading the documentation, this is actually signing the buffer with the private
key and not encrypting it.
DESCRIPTION
These functions handle RSA signatures at a low level.
RSA_private_encrypt() signs the flen bytes at from (usually a message digest with an algorithm identifier) using the private key rsa and stores the signature in to. to must point to RSA_size(rsa) bytes of memory.

Resources