test rsa private keys

This commit is contained in:
AJ ONeal 2019-02-07 20:05:26 +00:00
parent b9f5fd197e
commit 4afb5dc4cb
5 changed files with 148 additions and 33 deletions

View File

@ -0,0 +1,11 @@
{
"kty": "RSA",
"n": "m2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhDNzUJefLukC-xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57qAZM6-I70on0_iDZm7-jcqOPgADAmbWHhy67BXkk4yy_YzD4yOGZFXZcNp915_TW5bRd__AKPHUHxJasPiyEFqlNKBR2DSD-LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By5AB0Qi49OykUCfNZeQlEz7UNNj9RGps_50-CNw",
"e": "AQAB",
"d": "Cpfo7Mm9Nu8YMC_xrZ54W9mKHPkCG9rZ93Ds9PNp-RXUgb-ljTbFPZWsYxGNKLllFz8LNosr1pT2ZDMrwNk0Af1iWNvD6gkyXaiQdCyiDPSBsJyNv2LJZon-e85X74nv53UlIkmo9SYxdLz2JaJ-iIWEe8Qh-7llLktrTJV_xr98_tbhgSppz_IeOymq3SEZaQHM8pTU7w7XvCj2pb9r8fN0M0XcgWZIaf3LGEfkhF_WtX67XJ0C6-LbkT51jtlLRNGX6haGdscXS0OWWjKOJzKGuV-NbthEn5rmRtVnjRZ3yaxQ0ud8vC-NONn7yvGUlOur1IdDzJ_YfHPt9sHMQQ",
"p": "ynG-t9HwKCN3MWRYFdnFzi9-02Qcy3p8B5pu3ary2E70hYn2pHlUG2a9BNE8c5xHQ3Hx43WoWf6s0zOunPV1G28LkU_UYEbAtPv_PxSmzpQp9n9XnYvBLBF8Y3z7gxgLn1vVFNARrQdRtj87qY3aw7E9S4DsGcAarIuOT2TsTCE",
"q": "xIkAjgUzB1zaUzJtW2Zgvp9cYYr1DmpH30ePZl3c_8397_DZDDo46fnFYjs6uPa03HpmKUnbjwr14QHlfXlntJBEuXxcqLjkdKdJ4ob7xueLTK4suo9V8LSrkLChVxlZQwnFD2E5ll0sVeeDeMJHQw38ahSrBFEVnxjpnPh1Q1c",
"dp": "tzDGjECFOU0ehqtuqhcuT63a7h8hj19-7MJqoFwY9HQ-ALkfXyYLXeBSGxHbyiIYuodZg6LsfMNgUJ3r3Eyhc_nAVfYPEC_2IdAG4WYmq7iXYF9LQV09qEsKbFykm7QekE3hO7wswo5k-q2tp3ieBYdVGAXJoGOdv5VpaZ7B1QE",
"dq": "kh5dyDk7YCz7sUFbpsmuAeuPjoH2ghooh2u3xN7iUVmAg-ToKjwbVnG5-7eXiC779rQVwnrD_0yh1AFJ8wjRPqDIR7ObXGHikIxT1VSQWqiJm6AfZzDsL0LUD4YS3iPdhob7-NxLKWzqao_u4lhnDQaX9PKa12HFlny6K1daL48",
"qi": "AlHWbx1gp6Z9pbw_1hlS7HuXAgWoX7IjbTUelldf4gkriDWLOrj3QCZcO4ZvZvEwJhVlsny9LO8IkbwGJEL6cXraK08ByVS2mwQyflgTgGNnpzixyEUL_mrQLx6y145FHcxfeqNInMhep-0Mxn1D5nlhmIOgRApS0t9VoXtHhFU"
}

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAm2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhD
NzUJefLukC+xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ
38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57
qAZM6+I70on0/iDZm7+jcqOPgADAmbWHhy67BXkk4yy/YzD4yOGZFXZcNp915/TW
5bRd//AKPHUHxJasPiyEFqlNKBR2DSD+LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By
5AB0Qi49OykUCfNZeQlEz7UNNj9RGps/50+CNwIDAQABAoIBAAqX6OzJvTbvGDAv
8a2eeFvZihz5Ahva2fdw7PTzafkV1IG/pY02xT2VrGMRjSi5ZRc/CzaLK9aU9mQz
K8DZNAH9Yljbw+oJMl2okHQsogz0gbCcjb9iyWaJ/nvOV++J7+d1JSJJqPUmMXS8
9iWifoiFhHvEIfu5ZS5La0yVf8a/fP7W4YEqac/yHjspqt0hGWkBzPKU1O8O17wo
9qW/a/HzdDNF3IFmSGn9yxhH5IRf1rV+u1ydAuvi25E+dY7ZS0TRl+oWhnbHF0tD
lloyjicyhrlfjW7YRJ+a5kbVZ40Wd8msUNLnfLwvjTjZ+8rxlJTrq9SHQ8yf2Hxz
7fbBzEECgYEAynG+t9HwKCN3MWRYFdnFzi9+02Qcy3p8B5pu3ary2E70hYn2pHlU
G2a9BNE8c5xHQ3Hx43WoWf6s0zOunPV1G28LkU/UYEbAtPv/PxSmzpQp9n9XnYvB
LBF8Y3z7gxgLn1vVFNARrQdRtj87qY3aw7E9S4DsGcAarIuOT2TsTCECgYEAxIkA
jgUzB1zaUzJtW2Zgvp9cYYr1DmpH30ePZl3c/8397/DZDDo46fnFYjs6uPa03Hpm
KUnbjwr14QHlfXlntJBEuXxcqLjkdKdJ4ob7xueLTK4suo9V8LSrkLChVxlZQwnF
D2E5ll0sVeeDeMJHQw38ahSrBFEVnxjpnPh1Q1cCgYEAtzDGjECFOU0ehqtuqhcu
T63a7h8hj19+7MJqoFwY9HQ+ALkfXyYLXeBSGxHbyiIYuodZg6LsfMNgUJ3r3Eyh
c/nAVfYPEC/2IdAG4WYmq7iXYF9LQV09qEsKbFykm7QekE3hO7wswo5k+q2tp3ie
BYdVGAXJoGOdv5VpaZ7B1QECgYEAkh5dyDk7YCz7sUFbpsmuAeuPjoH2ghooh2u3
xN7iUVmAg+ToKjwbVnG5+7eXiC779rQVwnrD/0yh1AFJ8wjRPqDIR7ObXGHikIxT
1VSQWqiJm6AfZzDsL0LUD4YS3iPdhob7+NxLKWzqao/u4lhnDQaX9PKa12HFlny6
K1daL48CgYACUdZvHWCnpn2lvD/WGVLse5cCBahfsiNtNR6WV1/iCSuINYs6uPdA
Jlw7hm9m8TAmFWWyfL0s7wiRvAYkQvpxetorTwHJVLabBDJ+WBOAY2enOLHIRQv+
atAvHrLXjkUdzF96o0icyF6n7QzGfUPmeWGYg6BEClLS31Whe0eEVQ==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCba21UHE+VbDTp
mYYFZUOV+OQ8AngOCdjROsPC0KiEfMvEaEM3NQl58u6QL7G7QsErKViiNPm9OTFo
6HF5JijfWzK7haHFuRMEsgI4VwIYyhvqlJDfw/wt0AiVvSmoMfEQn1p1aiaO4V/R
JSE3Vw/uz2bxiT22uSkSqOyShyfYE6dMHnuoBkzr4jvSifT+INmbv6Nyo4+AAMCZ
tYeHLrsFeSTjLL9jMPjI4ZkVdlw2n3Xn9NbltF3/8Ao8dQfElqw+LIQWqU0oFHYN
IP4ttfl5ObMKHaKSvBMyNruZR0El/ZsrcHLkAHRCLj07KRQJ81l5CUTPtQ02P1Ea
mz/nT4I3AgMBAAECggEACpfo7Mm9Nu8YMC/xrZ54W9mKHPkCG9rZ93Ds9PNp+RXU
gb+ljTbFPZWsYxGNKLllFz8LNosr1pT2ZDMrwNk0Af1iWNvD6gkyXaiQdCyiDPSB
sJyNv2LJZon+e85X74nv53UlIkmo9SYxdLz2JaJ+iIWEe8Qh+7llLktrTJV/xr98
/tbhgSppz/IeOymq3SEZaQHM8pTU7w7XvCj2pb9r8fN0M0XcgWZIaf3LGEfkhF/W
tX67XJ0C6+LbkT51jtlLRNGX6haGdscXS0OWWjKOJzKGuV+NbthEn5rmRtVnjRZ3
yaxQ0ud8vC+NONn7yvGUlOur1IdDzJ/YfHPt9sHMQQKBgQDKcb630fAoI3cxZFgV
2cXOL37TZBzLenwHmm7dqvLYTvSFifakeVQbZr0E0TxznEdDcfHjdahZ/qzTM66c
9XUbbwuRT9RgRsC0+/8/FKbOlCn2f1edi8EsEXxjfPuDGAufW9UU0BGtB1G2Pzup
jdrDsT1LgOwZwBqsi45PZOxMIQKBgQDEiQCOBTMHXNpTMm1bZmC+n1xhivUOakff
R49mXdz/zf3v8NkMOjjp+cViOzq49rTcemYpSduPCvXhAeV9eWe0kES5fFyouOR0
p0nihvvG54tMriy6j1XwtKuQsKFXGVlDCcUPYTmWXSxV54N4wkdDDfxqFKsEURWf
GOmc+HVDVwKBgQC3MMaMQIU5TR6Gq26qFy5PrdruHyGPX37swmqgXBj0dD4AuR9f
Jgtd4FIbEdvKIhi6h1mDoux8w2BQnevcTKFz+cBV9g8QL/Yh0AbhZiaruJdgX0tB
XT2oSwpsXKSbtB6QTeE7vCzCjmT6ra2neJ4Fh1UYBcmgY52/lWlpnsHVAQKBgQCS
Hl3IOTtgLPuxQVumya4B64+OgfaCGiiHa7fE3uJRWYCD5OgqPBtWcbn7t5eILvv2
tBXCesP/TKHUAUnzCNE+oMhHs5tcYeKQjFPVVJBaqImboB9nMOwvQtQPhhLeI92G
hvv43EspbOpqj+7iWGcNBpf08prXYcWWfLorV1ovjwKBgAJR1m8dYKemfaW8P9YZ
Uux7lwIFqF+yI201HpZXX+IJK4g1izq490AmXDuGb2bxMCYVZbJ8vSzvCJG8BiRC
+nF62itPAclUtpsEMn5YE4BjZ6c4schFC/5q0C8esteORR3MX3qjSJzIXqftDMZ9
Q+Z5YZiDoEQKUtLfVaF7R4RV
-----END PRIVATE KEY-----

View File

@ -70,7 +70,7 @@ func PackPublicJWK(key crypto.PublicKey) (pub PublicJWK) {
// thumbprint keys are alphabetically sorted and only include the necessary public parts // thumbprint keys are alphabetically sorted and only include the necessary public parts
switch k := key.(type) { switch k := key.(type) {
case *rsa.PublicKey: case *rsa.PublicKey:
pub = marshalRSAPublicKey(k) pub = MarshalRSAPublicKey(k)
case *ecdsa.PublicKey: case *ecdsa.PublicKey:
pub = MarshalECPublicKey(k) pub = MarshalECPublicKey(k)
case *dsa.PublicKey: case *dsa.PublicKey:
@ -83,31 +83,51 @@ func PackPublicJWK(key crypto.PublicKey) (pub PublicJWK) {
return return
} }
func ThumbprintPublicKey(pub crypto.PublicKey) string {
switch p := pub.(type) {
case *ecdsa.PublicKey:
return ThumbprintECPublicKey(p)
case *rsa.PublicKey:
return ThumbprintRSAPublicKey(p)
default:
panic(EInvalidPublicKey)
}
}
func MarshalECPublicKey(k *ecdsa.PublicKey) PublicJWK { func MarshalECPublicKey(k *ecdsa.PublicKey) PublicJWK {
pub := PublicJWK{} pub := PublicJWK{}
pub.thumbprint = thumbstr(ThumbprintECPublicKey(k)) pub.thumbprint = thumbstr(ThumbprintECPublicKey(k))
crv := k.Curve.Params().Name
x := base64.RawURLEncoding.EncodeToString(k.X.Bytes()) x := base64.RawURLEncoding.EncodeToString(k.X.Bytes())
y := base64.RawURLEncoding.EncodeToString(k.Y.Bytes()) y := base64.RawURLEncoding.EncodeToString(k.Y.Bytes())
pub.jwk = jwkstr(fmt.Sprintf(`{"kid":%q,"crv":%q,"kty":"EC","x":%q,"y":%q}`, pub.Thumbprint(), k.Curve, x, y)) pub.jwk = jwkstr(fmt.Sprintf(`{"kid":%q,"crv":%q,"kty":"EC","x":%q,"y":%q}`, pub.Thumbprint(), crv, x, y))
return pub return pub
} }
func ThumbprintECPublicKey(k *ecdsa.PublicKey) string { func ThumbprintECPublicKey(k *ecdsa.PublicKey) string {
crv := k.Curve.Params().Name
x := base64.RawURLEncoding.EncodeToString(k.X.Bytes()) x := base64.RawURLEncoding.EncodeToString(k.X.Bytes())
y := base64.RawURLEncoding.EncodeToString(k.Y.Bytes()) y := base64.RawURLEncoding.EncodeToString(k.Y.Bytes())
thumbprintable := []byte(fmt.Sprintf(`{"crv":%q,"kty":"EC","x":%q,"y":%q}`, k.Curve, x, y)) thumbprintable := []byte(fmt.Sprintf(`{"crv":%q,"kty":"EC","x":%q,"y":%q}`, crv, x, y))
sha := sha256.Sum256(thumbprintable) sha := sha256.Sum256(thumbprintable)
return base64.RawURLEncoding.EncodeToString(sha[:]) return base64.RawURLEncoding.EncodeToString(sha[:])
} }
func marshalRSAPublicKey(k *rsa.PublicKey) (pub PublicJWK) { func MarshalRSAPublicKey(p *rsa.PublicKey) PublicJWK {
e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(k.E)).Bytes()) pub := PublicJWK{}
n := base64.RawURLEncoding.EncodeToString(k.N.Bytes()) pub.thumbprint = thumbstr(ThumbprintRSAPublicKey(p))
e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(p.E)).Bytes())
n := base64.RawURLEncoding.EncodeToString(p.N.Bytes())
pub.jwk = jwkstr(fmt.Sprintf(`{"kid":%q,"e":%q,"kty":"RSA","n":%q}`, pub.Thumbprint(), e, n))
return pub
}
func ThumbprintRSAPublicKey(p *rsa.PublicKey) string {
e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(p.E)).Bytes())
n := base64.RawURLEncoding.EncodeToString(p.N.Bytes())
thumbprintable := fmt.Sprintf(`{"e":%q,"kty":"RSA","n":%q}`, e, n) thumbprintable := fmt.Sprintf(`{"e":%q,"kty":"RSA","n":%q}`, e, n)
sha := sha256.Sum256([]byte(thumbprintable)) sha := sha256.Sum256([]byte(thumbprintable))
pub.thumbprint = thumbstr(base64.RawURLEncoding.EncodeToString(sha[:])) return base64.RawURLEncoding.EncodeToString(sha[:])
pub.jwk = jwkstr(fmt.Sprintf(`{"kid":%q,"e":%q,"kty":"RSA","n":%q}`, pub.Thumbprint(), e, n))
return
} }
func ParsePrivateKey(block []byte) (PrivateKey, error) { func ParsePrivateKey(block []byte) (PrivateKey, error) {
@ -130,9 +150,6 @@ func ParsePrivateKey(block []byte) (PrivateKey, error) {
} }
} }
//fmt.Println("Blocks:")
//fmt.Println(blocks)
// Parse PEM blocks (openssl generates junk metadata blocks for ECs) // Parse PEM blocks (openssl generates junk metadata blocks for ECs)
// or the original DER, or the JWK // or the original DER, or the JWK
for i, _ := range blocks { for i, _ := range blocks {
@ -149,6 +166,7 @@ func ParsePrivateKey(block []byte) (PrivateKey, error) {
func parsePrivateKey(der []byte) (PrivateKey, error) { func parsePrivateKey(der []byte) (PrivateKey, error) {
var key PrivateKey var key PrivateKey
//fmt.Println("1. ParsePKCS8PrivateKey")
xkey, err := x509.ParsePKCS8PrivateKey(der) xkey, err := x509.ParsePKCS8PrivateKey(der)
if nil == err { if nil == err {
switch k := xkey.(type) { switch k := xkey.(type) {
@ -160,17 +178,16 @@ func parsePrivateKey(der []byte) (PrivateKey, error) {
// ignore nil and unknown key types // ignore nil and unknown key types
} }
} }
fmt.Println("1. ParsePKCS8PrivateKey")
if nil != err { if nil != err {
//fmt.Println("2. ParseECPrivateKey")
key, err = x509.ParseECPrivateKey(der) key, err = x509.ParseECPrivateKey(der)
fmt.Println("2. ParseECPrivateKey")
if nil != err { if nil != err {
//fmt.Println("3. ParsePKCS1PrivateKey")
key, err = x509.ParsePKCS1PrivateKey(der) key, err = x509.ParsePKCS1PrivateKey(der)
fmt.Println("3. ParsePKCS1PrivateKey")
if nil != err { if nil != err {
//fmt.Println("4. ParseJWKPrivateKey")
key, err = ParseJWKPrivateKey(der) key, err = ParseJWKPrivateKey(der)
fmt.Println("4. ParseJWKPrivateKey")
} }
} }
} }

View File

@ -2,36 +2,68 @@ package keypairs
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"fmt" "crypto/rsa"
"io/ioutil" "io/ioutil"
"testing" "testing"
) )
func TestLoadECJWK(t *testing.T) { // TODO package all fixtures with fileb0x
// TODO package all fixtures with fileb0x
keypaths := []string{ func TestParsePrivateKeyEC(t *testing.T) {
"fixtures/privkey-ec-p256.jwk.json", keys := [][]string{
"fixtures/privkey-ec-p256.sec1.pem", // has openssl EC Param block []string{"fixtures/privkey-ec-p256.jwk.json", "bJiCcZHuAF9dDetKEdGjJU3pFvFLoB_QHe9_6cAuY8c"},
"fixtures/privkey-ec-p256.pkcs8.pem", // has openssl EC Param block
"fixtures/privkey-ec-p384.jwk.json", []string{"fixtures/privkey-ec-p256.sec1.pem", "bJiCcZHuAF9dDetKEdGjJU3pFvFLoB_QHe9_6cAuY8c"},
"fixtures/privkey-ec-p384.sec1.pem", []string{"fixtures/privkey-ec-p256.pkcs8.pem", "bJiCcZHuAF9dDetKEdGjJU3pFvFLoB_QHe9_6cAuY8c"},
"fixtures/privkey-ec-p384.pkcs8.pem",
[]string{"fixtures/privkey-ec-p384.jwk.json", "-WoRXrk3FZ7tGi8oj5wJHDDfFMBCGlUbpwil1WhpxrU"},
[]string{"fixtures/privkey-ec-p384.sec1.pem", "-WoRXrk3FZ7tGi8oj5wJHDDfFMBCGlUbpwil1WhpxrU"},
[]string{"fixtures/privkey-ec-p384.pkcs8.pem", "-WoRXrk3FZ7tGi8oj5wJHDDfFMBCGlUbpwil1WhpxrU"},
} }
for i := range keypaths { for i := range keys {
path := keypaths[i] path := keys[i][0]
fmt.Println("\n", path) thumb := keys[i][1]
b, err := ioutil.ReadFile(path) b, err := ioutil.ReadFile(path)
if nil != err { if nil != err {
t.Fatal(err) t.Fatal(path, err)
} }
key, err := ParsePrivateKey(b) key, err := ParsePrivateKey(b)
if nil != err { if nil != err {
t.Fatal(err) t.Fatal(path, err)
} }
eckey := key.(*ecdsa.PrivateKey) eckey := key.(*ecdsa.PrivateKey)
thumb := ThumbprintECPublicKey(eckey.Public().(*ecdsa.PublicKey)) thumb2 := ThumbprintECPublicKey(eckey.Public().(*ecdsa.PublicKey))
fmt.Println(thumb) if thumb != thumb2 {
t.Fatalf("EC thumbprints do not match: %q, %q, %q", path, thumb, thumb2)
}
}
}
func TestParsePrivateKeyRSA(t *testing.T) {
keypaths := []string{
"fixtures/privkey-rsa-2048.jwk.json",
"fixtures/privkey-rsa-2048.pkcs1.pem",
"fixtures/privkey-rsa-2048.pkcs8.pem",
}
for i := range keypaths {
path := keypaths[i]
b, err := ioutil.ReadFile(path)
if nil != err {
t.Fatal(path, err)
}
key, err := ParsePrivateKey(b)
if nil != err {
t.Fatal(path, err)
}
rsakey := key.(*rsa.PrivateKey)
thumb := "UIyZzFXPL-mTLnxQeSAHgu7gV16tro3evksnFb8fFQQ"
thumb2 := ThumbprintRSAPublicKey(rsakey.Public().(*rsa.PublicKey))
if thumb != thumb2 {
t.Fatalf("RSA thumbprints do not match: %q, %q, %q", path, thumb, thumb2)
}
} }
} }