1package dns 2 3import ( 4 "crypto" 5 "crypto/dsa" 6 "crypto/ecdsa" 7 "crypto/rsa" 8 "math/big" 9 "strconv" 10 11 "golang.org/x/crypto/ed25519" 12) 13 14const format = "Private-key-format: v1.3\n" 15 16var bigIntOne = big.NewInt(1) 17 18// PrivateKeyString converts a PrivateKey to a string. This string has the same 19// format as the private-key-file of BIND9 (Private-key-format: v1.3). 20// It needs some info from the key (the algorithm), so its a method of the DNSKEY 21// It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey 22func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string { 23 algorithm := strconv.Itoa(int(r.Algorithm)) 24 algorithm += " (" + AlgorithmToString[r.Algorithm] + ")" 25 26 switch p := p.(type) { 27 case *rsa.PrivateKey: 28 modulus := toBase64(p.PublicKey.N.Bytes()) 29 e := big.NewInt(int64(p.PublicKey.E)) 30 publicExponent := toBase64(e.Bytes()) 31 privateExponent := toBase64(p.D.Bytes()) 32 prime1 := toBase64(p.Primes[0].Bytes()) 33 prime2 := toBase64(p.Primes[1].Bytes()) 34 // Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm 35 // and from: http://code.google.com/p/go/issues/detail?id=987 36 p1 := new(big.Int).Sub(p.Primes[0], bigIntOne) 37 q1 := new(big.Int).Sub(p.Primes[1], bigIntOne) 38 exp1 := new(big.Int).Mod(p.D, p1) 39 exp2 := new(big.Int).Mod(p.D, q1) 40 coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0]) 41 42 exponent1 := toBase64(exp1.Bytes()) 43 exponent2 := toBase64(exp2.Bytes()) 44 coefficient := toBase64(coeff.Bytes()) 45 46 return format + 47 "Algorithm: " + algorithm + "\n" + 48 "Modulus: " + modulus + "\n" + 49 "PublicExponent: " + publicExponent + "\n" + 50 "PrivateExponent: " + privateExponent + "\n" + 51 "Prime1: " + prime1 + "\n" + 52 "Prime2: " + prime2 + "\n" + 53 "Exponent1: " + exponent1 + "\n" + 54 "Exponent2: " + exponent2 + "\n" + 55 "Coefficient: " + coefficient + "\n" 56 57 case *ecdsa.PrivateKey: 58 var intlen int 59 switch r.Algorithm { 60 case ECDSAP256SHA256: 61 intlen = 32 62 case ECDSAP384SHA384: 63 intlen = 48 64 } 65 private := toBase64(intToBytes(p.D, intlen)) 66 return format + 67 "Algorithm: " + algorithm + "\n" + 68 "PrivateKey: " + private + "\n" 69 70 case *dsa.PrivateKey: 71 T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8) 72 prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8)) 73 subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20)) 74 base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8)) 75 priv := toBase64(intToBytes(p.X, 20)) 76 pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8)) 77 return format + 78 "Algorithm: " + algorithm + "\n" + 79 "Prime(p): " + prime + "\n" + 80 "Subprime(q): " + subprime + "\n" + 81 "Base(g): " + base + "\n" + 82 "Private_value(x): " + priv + "\n" + 83 "Public_value(y): " + pub + "\n" 84 85 case ed25519.PrivateKey: 86 private := toBase64(p.Seed()) 87 return format + 88 "Algorithm: " + algorithm + "\n" + 89 "PrivateKey: " + private + "\n" 90 91 default: 92 return "" 93 } 94} 95