1package dns 2 3import ( 4 "crypto" 5 "crypto/dsa" 6 "crypto/ecdsa" 7 "crypto/elliptic" 8 "crypto/rand" 9 "crypto/rsa" 10 "math/big" 11) 12 13// Generate generates a DNSKEY of the given bit size. 14// The public part is put inside the DNSKEY record. 15// The Algorithm in the key must be set as this will define 16// what kind of DNSKEY will be generated. 17// The ECDSA algorithms imply a fixed keysize, in that case 18// bits should be set to the size of the algorithm. 19func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) { 20 switch k.Algorithm { 21 case DSA, DSANSEC3SHA1: 22 if bits != 1024 { 23 return nil, ErrKeySize 24 } 25 case RSAMD5, RSASHA1, RSASHA256, RSASHA1NSEC3SHA1: 26 if bits < 512 || bits > 4096 { 27 return nil, ErrKeySize 28 } 29 case RSASHA512: 30 if bits < 1024 || bits > 4096 { 31 return nil, ErrKeySize 32 } 33 case ECDSAP256SHA256: 34 if bits != 256 { 35 return nil, ErrKeySize 36 } 37 case ECDSAP384SHA384: 38 if bits != 384 { 39 return nil, ErrKeySize 40 } 41 } 42 43 switch k.Algorithm { 44 case DSA, DSANSEC3SHA1: 45 params := new(dsa.Parameters) 46 if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil { 47 return nil, err 48 } 49 priv := new(dsa.PrivateKey) 50 priv.PublicKey.Parameters = *params 51 err := dsa.GenerateKey(priv, rand.Reader) 52 if err != nil { 53 return nil, err 54 } 55 k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y) 56 return priv, nil 57 case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1: 58 priv, err := rsa.GenerateKey(rand.Reader, bits) 59 if err != nil { 60 return nil, err 61 } 62 k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N) 63 return priv, nil 64 case ECDSAP256SHA256, ECDSAP384SHA384: 65 var c elliptic.Curve 66 switch k.Algorithm { 67 case ECDSAP256SHA256: 68 c = elliptic.P256() 69 case ECDSAP384SHA384: 70 c = elliptic.P384() 71 } 72 priv, err := ecdsa.GenerateKey(c, rand.Reader) 73 if err != nil { 74 return nil, err 75 } 76 k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y) 77 return priv, nil 78 default: 79 return nil, ErrAlg 80 } 81} 82 83// Set the public key (the value E and N) 84func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool { 85 if _E == 0 || _N == nil { 86 return false 87 } 88 buf := exponentToBuf(_E) 89 buf = append(buf, _N.Bytes()...) 90 k.PublicKey = toBase64(buf) 91 return true 92} 93 94// Set the public key for Elliptic Curves 95func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool { 96 if _X == nil || _Y == nil { 97 return false 98 } 99 var intlen int 100 switch k.Algorithm { 101 case ECDSAP256SHA256: 102 intlen = 32 103 case ECDSAP384SHA384: 104 intlen = 48 105 } 106 k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen)) 107 return true 108} 109 110// Set the public key for DSA 111func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool { 112 if _Q == nil || _P == nil || _G == nil || _Y == nil { 113 return false 114 } 115 buf := dsaToBuf(_Q, _P, _G, _Y) 116 k.PublicKey = toBase64(buf) 117 return true 118} 119 120// Set the public key (the values E and N) for RSA 121// RFC 3110: Section 2. RSA Public KEY Resource Records 122func exponentToBuf(_E int) []byte { 123 var buf []byte 124 i := big.NewInt(int64(_E)).Bytes() 125 if len(i) < 256 { 126 buf = make([]byte, 1, 1+len(i)) 127 buf[0] = uint8(len(i)) 128 } else { 129 buf = make([]byte, 3, 3+len(i)) 130 buf[0] = 0 131 buf[1] = uint8(len(i) >> 8) 132 buf[2] = uint8(len(i)) 133 } 134 buf = append(buf, i...) 135 return buf 136} 137 138// Set the public key for X and Y for Curve. The two 139// values are just concatenated. 140func curveToBuf(_X, _Y *big.Int, intlen int) []byte { 141 buf := intToBytes(_X, intlen) 142 buf = append(buf, intToBytes(_Y, intlen)...) 143 return buf 144} 145 146// Set the public key for X and Y for Curve. The two 147// values are just concatenated. 148func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte { 149 t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8) 150 buf := []byte{byte(t)} 151 buf = append(buf, intToBytes(_Q, 20)...) 152 buf = append(buf, intToBytes(_P, 64+t*8)...) 153 buf = append(buf, intToBytes(_G, 64+t*8)...) 154 buf = append(buf, intToBytes(_Y, 64+t*8)...) 155 return buf 156} 157