Reputation: 21
I'm having trouble accessing the PublicKey
field of *rsa.PrivateKey
Whenever I call x509.MarshalPKCS1PublicKey(keyBytes.PublicKey)
in the code below, I get:
[tony@localhost app]$ go run gencsr.go
# command-line-arguments
./gencsr.go:37:90: undefined: x509.MarshalPKCS1PublicKey
As you can see, I've included the x509
package and I'm able to access keyBytes.PublicKey
and see that it's of type PublicKey
.
Sources:
crypto/x509
crypto/rsa
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"fmt"
)
var oidEmailAddress = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}
func main() {
email := ""
subj := pkix.Name{
CommonName: "example.com",
Country: []string{"US"},
Province: []string{"New York"},
Locality: []string{"Albany"},
Organization: []string{"My Company Ltd"},
OrganizationalUnit: []string{"IT"},
}
bits := 4096
key, csr := genCSR(subj, email, bits)
fmt.Printf(key)
fmt.Printf(csr)
}
func genCSR(subj pkix.Name, email string, bits int) (pemKey, csr string) {
keyBytes, _ := rsa.GenerateKey(rand.Reader, bits)
pemPubKey := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: x509.MarshalPKCS1PublicKey(keyBytes.PublicKey)}))
pemKey = string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(keyBytes)}))
fmt.Printf(pemPubKey)
rawSubj := subj.ToRDNSequence()
if len(email) > 0 {
rawSubj = append(rawSubj, []pkix.AttributeTypeAndValue{
{Type: oidEmailAddress, Value: email},
})
}
asn1Subj, _ := asn1.Marshal(rawSubj)
template := x509.CertificateRequest{
RawSubject: asn1Subj,
SignatureAlgorithm: x509.SHA256WithRSA,
}
csrBytes, _ := x509.CreateCertificateRequest(rand.Reader, &template, keyBytes)
csr = string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes}))
return pemKey, csr
}
Upvotes: 2
Views: 1311
Reputation: 2858
RSA public key can be generated this way:
package main
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"golang.org/x/crypto/ssh"
)
func main(){
key, b, err := generatePrivateKey()
if err != nil{
fmt.Println(err)
return
}
fmt.Println(string(b))
public2, err := generateSSHPublicKey(key)
if err != nil{
fmt.Println(err)
return
}
fmt.Println(string(public2))
}
func generatePrivateKey() (*rsa.PrivateKey, []byte, error) {
// keyBytes, err := rsa.GenerateKey(rand.Reader, 2048)
keyBytes, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return nil, nil, err
}
certBytes := new(bytes.Buffer)
err = pem.Encode(certBytes, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(keyBytes)})
if err != nil{
return nil, nil, err
}
return keyBytes, certBytes.Bytes(), nil
}
func generateSSHPublicKey(key *rsa.PrivateKey) ([]byte, error){
public, err := ssh.NewPublicKey(&key.PublicKey) // *rsaPublicKey
if err != nil{
return nil, err
}
certBytes := new(bytes.Buffer)
err = pem.Encode(certBytes, &pem.Block{Type: "PUBLIC KEY", Bytes: public.Marshal()})
if err != nil{
return nil, err
}
return certBytes.Bytes(), nil
}
Upvotes: 0
Reputation: 31721
x509.MarshalPKCS1PublicKey is new in Go 1.10. You are probably running an older version.
If you can't upgrade: the function is very simple and you can just copy it into your own package:
// pkcs1PublicKey reflects the ASN.1 structure of a PKCS#1 public key.
type pkcs1PublicKey struct {
N *big.Int
E int
}
// MarshalPKCS1PublicKey converts an RSA public key to PKCS#1, ASN.1 DER form.
func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte {
derBytes, _ := asn1.Marshal(pkcs1PublicKey{
N: key.N,
E: key.E,
})
return derBytes
}
Upvotes: 2