dnssec_keyscan.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. package dns
  2. import (
  3. "crypto"
  4. "crypto/dsa"
  5. "crypto/ecdsa"
  6. "crypto/rsa"
  7. "io"
  8. "math/big"
  9. "strconv"
  10. "strings"
  11. )
  12. // NewPrivateKey returns a PrivateKey by parsing the string s.
  13. // s should be in the same form of the BIND private key files.
  14. func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
  15. if s[len(s)-1] != '\n' { // We need a closing newline
  16. return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
  17. }
  18. return k.ReadPrivateKey(strings.NewReader(s), "")
  19. }
  20. // ReadPrivateKey reads a private key from the io.Reader q. The string file is
  21. // only used in error reporting.
  22. // The public key must be known, because some cryptographic algorithms embed
  23. // the public inside the privatekey.
  24. func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
  25. m, e := parseKey(q, file)
  26. if m == nil {
  27. return nil, e
  28. }
  29. if _, ok := m["private-key-format"]; !ok {
  30. return nil, ErrPrivKey
  31. }
  32. if m["private-key-format"] != "v1.2" && m["private-key-format"] != "v1.3" {
  33. return nil, ErrPrivKey
  34. }
  35. // TODO(mg): check if the pubkey matches the private key
  36. algo, err := strconv.Atoi(strings.SplitN(m["algorithm"], " ", 2)[0])
  37. if err != nil {
  38. return nil, ErrPrivKey
  39. }
  40. switch uint8(algo) {
  41. case DSA:
  42. priv, e := readPrivateKeyDSA(m)
  43. if e != nil {
  44. return nil, e
  45. }
  46. pub := k.publicKeyDSA()
  47. if pub == nil {
  48. return nil, ErrKey
  49. }
  50. priv.PublicKey = *pub
  51. return priv, e
  52. case RSAMD5:
  53. fallthrough
  54. case RSASHA1:
  55. fallthrough
  56. case RSASHA1NSEC3SHA1:
  57. fallthrough
  58. case RSASHA256:
  59. fallthrough
  60. case RSASHA512:
  61. priv, e := readPrivateKeyRSA(m)
  62. if e != nil {
  63. return nil, e
  64. }
  65. pub := k.publicKeyRSA()
  66. if pub == nil {
  67. return nil, ErrKey
  68. }
  69. priv.PublicKey = *pub
  70. return priv, e
  71. case ECCGOST:
  72. return nil, ErrPrivKey
  73. case ECDSAP256SHA256:
  74. fallthrough
  75. case ECDSAP384SHA384:
  76. priv, e := readPrivateKeyECDSA(m)
  77. if e != nil {
  78. return nil, e
  79. }
  80. pub := k.publicKeyECDSA()
  81. if pub == nil {
  82. return nil, ErrKey
  83. }
  84. priv.PublicKey = *pub
  85. return priv, e
  86. default:
  87. return nil, ErrPrivKey
  88. }
  89. }
  90. // Read a private key (file) string and create a public key. Return the private key.
  91. func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
  92. p := new(rsa.PrivateKey)
  93. p.Primes = []*big.Int{nil, nil}
  94. for k, v := range m {
  95. switch k {
  96. case "modulus", "publicexponent", "privateexponent", "prime1", "prime2":
  97. v1, err := fromBase64([]byte(v))
  98. if err != nil {
  99. return nil, err
  100. }
  101. switch k {
  102. case "modulus":
  103. p.PublicKey.N = big.NewInt(0)
  104. p.PublicKey.N.SetBytes(v1)
  105. case "publicexponent":
  106. i := big.NewInt(0)
  107. i.SetBytes(v1)
  108. p.PublicKey.E = int(i.Int64()) // int64 should be large enough
  109. case "privateexponent":
  110. p.D = big.NewInt(0)
  111. p.D.SetBytes(v1)
  112. case "prime1":
  113. p.Primes[0] = big.NewInt(0)
  114. p.Primes[0].SetBytes(v1)
  115. case "prime2":
  116. p.Primes[1] = big.NewInt(0)
  117. p.Primes[1].SetBytes(v1)
  118. }
  119. case "exponent1", "exponent2", "coefficient":
  120. // not used in Go (yet)
  121. case "created", "publish", "activate":
  122. // not used in Go (yet)
  123. }
  124. }
  125. return p, nil
  126. }
  127. func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
  128. p := new(dsa.PrivateKey)
  129. p.X = big.NewInt(0)
  130. for k, v := range m {
  131. switch k {
  132. case "private_value(x)":
  133. v1, err := fromBase64([]byte(v))
  134. if err != nil {
  135. return nil, err
  136. }
  137. p.X.SetBytes(v1)
  138. case "created", "publish", "activate":
  139. /* not used in Go (yet) */
  140. }
  141. }
  142. return p, nil
  143. }
  144. func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
  145. p := new(ecdsa.PrivateKey)
  146. p.D = big.NewInt(0)
  147. // TODO: validate that the required flags are present
  148. for k, v := range m {
  149. switch k {
  150. case "privatekey":
  151. v1, err := fromBase64([]byte(v))
  152. if err != nil {
  153. return nil, err
  154. }
  155. p.D.SetBytes(v1)
  156. case "created", "publish", "activate":
  157. /* not used in Go (yet) */
  158. }
  159. }
  160. return p, nil
  161. }
  162. // parseKey reads a private key from r. It returns a map[string]string,
  163. // with the key-value pairs, or an error when the file is not correct.
  164. func parseKey(r io.Reader, file string) (map[string]string, error) {
  165. s := scanInit(r)
  166. m := make(map[string]string)
  167. c := make(chan lex)
  168. k := ""
  169. // Start the lexer
  170. go klexer(s, c)
  171. for l := range c {
  172. // It should alternate
  173. switch l.value {
  174. case zKey:
  175. k = l.token
  176. case zValue:
  177. if k == "" {
  178. return nil, &ParseError{file, "no private key seen", l}
  179. }
  180. //println("Setting", strings.ToLower(k), "to", l.token, "b")
  181. m[strings.ToLower(k)] = l.token
  182. k = ""
  183. }
  184. }
  185. return m, nil
  186. }
  187. // klexer scans the sourcefile and returns tokens on the channel c.
  188. func klexer(s *scan, c chan lex) {
  189. var l lex
  190. str := "" // Hold the current read text
  191. commt := false
  192. key := true
  193. x, err := s.tokenText()
  194. defer close(c)
  195. for err == nil {
  196. l.column = s.position.Column
  197. l.line = s.position.Line
  198. switch x {
  199. case ':':
  200. if commt {
  201. break
  202. }
  203. l.token = str
  204. if key {
  205. l.value = zKey
  206. c <- l
  207. // Next token is a space, eat it
  208. s.tokenText()
  209. key = false
  210. str = ""
  211. } else {
  212. l.value = zValue
  213. }
  214. case ';':
  215. commt = true
  216. case '\n':
  217. if commt {
  218. // Reset a comment
  219. commt = false
  220. }
  221. l.value = zValue
  222. l.token = str
  223. c <- l
  224. str = ""
  225. commt = false
  226. key = true
  227. default:
  228. if commt {
  229. break
  230. }
  231. str += string(x)
  232. }
  233. x, err = s.tokenText()
  234. }
  235. if len(str) > 0 {
  236. // Send remainder
  237. l.token = str
  238. l.value = zValue
  239. c <- l
  240. }
  241. }