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