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