2018-06-24 23:46:42 -04:00
|
|
|
package activitypub
|
|
|
|
|
|
|
|
|
|
import (
|
2018-06-25 00:28:14 -04:00
|
|
|
"crypto"
|
2018-06-24 23:46:42 -04:00
|
|
|
"crypto/rsa"
|
|
|
|
|
"crypto/x509"
|
|
|
|
|
"encoding/pem"
|
|
|
|
|
"fmt"
|
2018-06-26 18:58:38 -04:00
|
|
|
"github.com/writeas/openssl-go"
|
2018-06-24 23:46:42 -04:00
|
|
|
"log"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const keyBitSize = 2048
|
|
|
|
|
|
2018-06-25 00:28:14 -04:00
|
|
|
// GenerateKeys creates an RSA keypair and returns the public and private key,
|
|
|
|
|
// in that order.
|
|
|
|
|
func GenerateKeys() (pubPEM []byte, privPEM []byte) {
|
2018-06-25 00:28:14 -04:00
|
|
|
var err error
|
2018-06-26 18:58:38 -04:00
|
|
|
privPEM, err = openssl.Call(nil, "genrsa", fmt.Sprintf("%d", keyBitSize))
|
2018-06-24 23:46:42 -04:00
|
|
|
if err != nil {
|
2018-06-25 00:28:14 -04:00
|
|
|
log.Printf("Unable to generate private key: %v", err)
|
2018-06-25 00:28:14 -04:00
|
|
|
return nil, nil
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
|
|
|
|
|
2018-06-26 18:58:38 -04:00
|
|
|
pubPEM, err = openssl.Call(privPEM, "rsa", "-in", "/dev/stdin", "-pubout")
|
2018-06-24 23:46:42 -04:00
|
|
|
if err != nil {
|
2018-06-25 00:28:14 -04:00
|
|
|
log.Printf("Unable to get public key: %v", err)
|
2018-06-25 00:28:14 -04:00
|
|
|
return nil, nil
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
2018-06-25 00:28:14 -04:00
|
|
|
return
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
|
|
|
|
|
2018-06-25 00:28:14 -04:00
|
|
|
func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
|
|
|
|
|
if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
|
|
|
|
|
return key, nil
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
2018-06-25 00:28:14 -04:00
|
|
|
if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
|
|
|
|
|
switch key := key.(type) {
|
|
|
|
|
case *rsa.PrivateKey:
|
|
|
|
|
return key, nil
|
|
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("found unknown private key type in PKCS#8 wrapping")
|
|
|
|
|
}
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
2018-06-25 00:28:14 -04:00
|
|
|
if key, err := x509.ParseECPrivateKey(der); err == nil {
|
|
|
|
|
return key, nil
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
|
|
|
|
|
2018-06-25 00:28:14 -04:00
|
|
|
return nil, fmt.Errorf("failed to parse private key")
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
|
|
|
|
|
2018-08-21 16:43:21 -04:00
|
|
|
func parsePublicKey(der []byte) (crypto.PublicKey, error) {
|
|
|
|
|
if key, err := x509.ParsePKCS1PublicKey(der); err == nil {
|
|
|
|
|
return key, nil
|
|
|
|
|
}
|
|
|
|
|
if key, err := x509.ParsePKIXPublicKey(der); err == nil {
|
|
|
|
|
switch key := key.(type) {
|
|
|
|
|
case *rsa.PublicKey:
|
|
|
|
|
return key, nil
|
|
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("found unknown public key type in PKIX wrapping")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("failed to parse public key")
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-24 23:46:42 -04:00
|
|
|
// DecodePrivateKey encodes public and private key to PEM format, returning
|
|
|
|
|
// them in that order.
|
2018-06-25 00:28:14 -04:00
|
|
|
func DecodePrivateKey(k []byte) (crypto.PrivateKey, error) {
|
2018-06-24 23:46:42 -04:00
|
|
|
block, _ := pem.Decode(k)
|
2022-11-11 01:56:53 -05:00
|
|
|
if block == nil || (block.Type != "RSA PRIVATE KEY" && block.Type != "PRIVATE KEY") {
|
|
|
|
|
return nil, fmt.Errorf("failed to decode PEM block containing private key, type %s", block.Type)
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
|
|
|
|
|
2018-06-25 00:28:14 -04:00
|
|
|
return parsePrivateKey(block.Bytes)
|
2018-06-24 23:46:42 -04:00
|
|
|
}
|
2018-08-21 16:43:21 -04:00
|
|
|
|
|
|
|
|
// DecodePublicKey decodes public keys
|
|
|
|
|
func DecodePublicKey(k []byte) (crypto.PublicKey, error) {
|
|
|
|
|
block, _ := pem.Decode(k)
|
|
|
|
|
if block == nil || block.Type != "PUBLIC KEY" {
|
|
|
|
|
if block != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to decode PEM block containing public key. type: %v", block.Type)
|
|
|
|
|
} else {
|
|
|
|
|
return nil, fmt.Errorf("failed to decode PEM block containing public key.")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return parsePublicKey(block.Bytes)
|
|
|
|
|
}
|