parse private key files

Reading a key should go as this:
k := new(key)
k.ReadPublic(File)
k.ReadPrivate(File)

For RSA enough public material is stored in the priv. key that we do it
in one swoop. This should really be two steps.
This commit is contained in:
Miek Gieben 2011-07-17 12:03:04 +02:00
parent 43d51f7382
commit b2c50a39f6
3 changed files with 757 additions and 286 deletions

111
keygen.go
View File

@ -4,9 +4,6 @@ import (
"os" "os"
"io" "io"
"big" "big"
"fmt"
"strings"
"bufio"
"strconv" "strconv"
"crypto/rsa" "crypto/rsa"
"crypto/ecdsa" "crypto/ecdsa"
@ -34,8 +31,12 @@ func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) {
if bits < 1024 || bits > 4096 { if bits < 1024 || bits > 4096 {
return nil, ErrKeySize return nil, ErrKeySize
} }
case ECDSAP256SHA256, ECDSAP384SHA384: case ECDSAP256SHA256:
if bits != 0 { if bits != 256 {
return nil, ErrKeySize
}
case ECDSAP384SHA384:
if bits != 384 {
return nil, ErrKeySize return nil, ErrKeySize
} }
} }
@ -112,68 +113,50 @@ func (r *RR_DNSKEY) PrivateKeyString(p PrivateKey) (s string) {
} }
func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader) (PrivateKey, os.Error) { func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader) (PrivateKey, os.Error) {
r := bufio.NewReader(q) kv, _ := Kparse(q)
line, _, err := r.ReadLine() if _, ok := kv["private-key-format"]; !ok {
private: return nil, ErrPrivKey
for err == nil {
str := strings.Split(string(line), ": ", 2)
switch str[0] {
case "Private-key-format":
if str[1] != "v1.2" && str[1] != "v1.3" {
return nil, ErrPrivKey
}
case "Algorithm":
// 5 (RSASHA1) for instance
a := strings.Split(str[1], " ", 2)
alg, _ := strconv.Atoi(a[0])
if alg == 0 {
return nil, ErrAlg
}
k.Algorithm = uint8(alg)
break private
}
line, _, err = r.ReadLine()
} }
switch k.Algorithm { if kv["private-key-format"] != "v1.2" || kv["private-key-format"] != "v1.3" {
case RSAMD5, RSASHA1, RSASHA256, RSASHA512: return nil, ErrPrivKey
return k.readPrivateKeyRSA(r) }
case ECDSAP256SHA256, ECDSAP384SHA384: switch kv["algorithm"] {
return k.readPrivateKeyECDSA(r) case "RSAMD5", "RSASHA1", "RSASHA256", "RSASHA512":
return k.readPrivateKeyRSA(kv)
case "ECDSAP256SHA256", "ECDSAP384SHA384":
return k.readPrivateKeyECDSA(kv)
} }
return nil, ErrKey return nil, ErrKey
} }
// Read a private key (file) string and create a public key. Return the private key. // Read a private key (file) string and create a public key. Return the private key.
func (k *RR_DNSKEY) readPrivateKeyRSA(r *bufio.Reader) (PrivateKey, os.Error) { func (k *RR_DNSKEY) readPrivateKeyRSA(kv map[string]string) (PrivateKey, os.Error) {
p := new(rsa.PrivateKey) p := new(rsa.PrivateKey)
p.Primes = []*big.Int{nil,nil} p.Primes = []*big.Int{nil,nil}
line, _, err := r.ReadLine() for k, v := range kv {
for err == nil { switch k {
str := strings.Split(string(line), ": ", 2)
switch str[0] {
case "Modulus", "PublicExponent", "PrivateExponent", "Prime1", "Prime2": case "Modulus", "PublicExponent", "PrivateExponent", "Prime1", "Prime2":
v, err := packBase64([]byte(str[1])) v1, err := packBase64([]byte(v))
if err != nil { if err != nil {
return nil, err return nil, err
} }
switch str[0] { switch k {
case "Modulus": case "Modulus":
p.PublicKey.N = big.NewInt(0) p.PublicKey.N = big.NewInt(0)
p.PublicKey.N.SetBytes(v) p.PublicKey.N.SetBytes(v1)
case "PublicExponent": case "PublicExponent":
i := big.NewInt(0) i := big.NewInt(0)
i.SetBytes(v) i.SetBytes(v1)
// Int64 should be large enough p.PublicKey.E = int(i.Int64()) // int64 should be large enough
p.PublicKey.E = int(i.Int64())
case "PrivateExponent": case "PrivateExponent":
p.D = big.NewInt(0) p.D = big.NewInt(0)
p.D.SetBytes(v) p.D.SetBytes(v1)
case "Prime1": case "Prime1":
p.Primes[0] = big.NewInt(0) p.Primes[0] = big.NewInt(0)
p.Primes[0].SetBytes(v) p.Primes[0].SetBytes(v1)
case "Prime2": case "Prime2":
p.Primes[1] = big.NewInt(0) p.Primes[1] = big.NewInt(0)
p.Primes[1].SetBytes(v) p.Primes[1].SetBytes(v1)
} }
case "Exponent1", "Exponent2", "Coefficient": case "Exponent1", "Exponent2", "Coefficient":
// not used in Go (yet) // not used in Go (yet)
@ -182,7 +165,6 @@ func (k *RR_DNSKEY) readPrivateKeyRSA(r *bufio.Reader) (PrivateKey, os.Error) {
default: default:
return nil, ErrKey return nil, ErrKey
} }
line, _, err = r.ReadLine()
} }
if ! k.setPublicKeyRSA(p.PublicKey.E, p.PublicKey.N) { if ! k.setPublicKeyRSA(p.PublicKey.E, p.PublicKey.N) {
return nil, ErrKey return nil, ErrKey
@ -190,30 +172,23 @@ func (k *RR_DNSKEY) readPrivateKeyRSA(r *bufio.Reader) (PrivateKey, os.Error) {
return p, nil return p, nil
} }
// Read a private key (file) string and create a public key. Return the private key. func (k *RR_DNSKEY) readPrivateKeyECDSA(kv map[string]string) (PrivateKey, os.Error) {
func (k *RR_DNSKEY) readPrivateKeyECDSA(r *bufio.Reader) (PrivateKey, os.Error) {
p := new(ecdsa.PrivateKey) p := new(ecdsa.PrivateKey)
p.D = big.NewInt(0) p.D = big.NewInt(0)
var left, right string for k, v := range kv {
line, _, err := r.ReadLine() switch k {
for err == nil { case "PrivateKey:":
n, _ := fmt.Sscanf(string(line), "%s %s+\n", &left, &right) v1, err := packBase64([]byte(v))
if n > 0 { if err != nil {
switch left { return nil, err
case "PrivateKey:": }
v, err := packBase64([]byte(right)) p.D.SetBytes(v1)
if err != nil { case "Created:", "Publish:", "Activate:":
return nil, err /* not used in Go (yet) */
} default:
p.D.SetBytes(v) return nil, ErrKey
case "Created:", "Publish:", "Activate:": }
/* not used in Go (yet) */ }
default:
return nil, ErrKey
}
}
line, _, err = r.ReadLine()
}
//if ! k.setPublicKeyRSA(p.PublicKey.E, p.PublicKey.N) { //if ! k.setPublicKeyRSA(p.PublicKey.E, p.PublicKey.N) {
// return nil, ErrKey // return nil, ErrKey
//} //}

925
kparse.go

File diff suppressed because it is too large Load Diff

View File

@ -28,8 +28,11 @@ func Kparse(q io.Reader) (m map[string]string, err os.Error) {
action mark { mark = p } action mark { mark = p }
action setKey { k = strings.ToLower(data[mark:p]) } action setKey { k = strings.ToLower(data[mark:p]) }
action setValue { m[k] = data[mark:p] } action setValue { m[k] = data[mark:p] }
action setAlg { m[k] = data[mark:p-1] }
base64 = [a-zA-Z0-9.\\/+=() ]+ >mark; bl = [ \t]+;
base64any = [a-zA-Z0-9.\\/+=() ]+ >mark;
algorithm = ( 'RSASHA1'i | 'RSASHA256'i ) >mark;
key = ( key = (
('Private-key-format'i) ('Private-key-format'i)
@ -49,7 +52,7 @@ func Kparse(q io.Reader) (m map[string]string, err os.Error) {
| ('Activate'i) | ('Activate'i)
) >mark %setKey; ) >mark %setKey;
value = base64 %setValue; value = ( base64any %setValue | digit+ bl '(' algorithm ')' %setAlg );
line = key ': ' value; line = key ': ' value;
main := ( line '\n' )*; main := ( line '\n' )*;