tls.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. package tls
  2. import (
  3. "crypto/ed25519"
  4. "crypto/rand"
  5. "crypto/x509"
  6. "crypto/x509/pkix"
  7. "encoding/base64"
  8. "encoding/pem"
  9. "errors"
  10. "fmt"
  11. "math/big"
  12. "os"
  13. "time"
  14. "filippo.io/edwards25519"
  15. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  16. )
  17. const (
  18. // CERTTIFICATE_VALIDITY duration of certificate validity in days
  19. CERTIFICATE_VALIDITY = 365
  20. // SERVER_KEY_NAME - name of server cert private key
  21. SERVER_KEY_NAME = "server.key"
  22. // ROOT_KEY_NAME - name of root cert private key
  23. ROOT_KEY_NAME = "root.key"
  24. // SERVER_PEM_NAME - name of server pem
  25. SERVER_PEM_NAME = "server.pem"
  26. // ROOT_PEM_NAME - name of root pem
  27. ROOT_PEM_NAME = "root.pem"
  28. // SERVER_CLIENT_PEM - the name of server client cert
  29. SERVER_CLIENT_PEM = "serverclient.pem"
  30. // SERVER_CLIENT_KEY - the name of server client key
  31. SERVER_CLIENT_KEY = "serverclient.key"
  32. // SERVER_CLIENT_ENTRY - the server client cert key for DB
  33. SERVER_CLIENT_ENTRY = "servercliententry"
  34. )
  35. type (
  36. // Key is the struct for an edwards representation point
  37. Key struct {
  38. point *edwards25519.Point
  39. }
  40. )
  41. // NewKey generates a new key.
  42. func NewKey() *Key {
  43. seed := make([]byte, 64)
  44. rand.Reader.Read(seed)
  45. s, _ := (&edwards25519.Scalar{}).SetUniformBytes(seed)
  46. return &Key{(&edwards25519.Point{}).ScalarBaseMult(s)}
  47. }
  48. // Key.Ed25519PrivateKey returns the private key in Edwards form used for EdDSA.
  49. func (n *Key) Ed25519PrivateKey() (ed25519.PrivateKey, error) {
  50. if n.point == nil {
  51. return ed25519.PrivateKey{}, errors.New("nil point")
  52. }
  53. if len(n.point.Bytes()) != ed25519.SeedSize {
  54. return ed25519.PrivateKey{}, errors.New("incorrect seed size")
  55. }
  56. return ed25519.NewKeyFromSeed(n.point.Bytes()), nil
  57. }
  58. // Key.Curve25519PrivateKey returns the private key in Montogomery form used for ECDH.
  59. func (n *Key) Curve25519PrivateKey() (wgtypes.Key, error) {
  60. if n.point == nil {
  61. return wgtypes.Key{}, errors.New("nil point")
  62. }
  63. if len(n.point.Bytes()) != ed25519.SeedSize {
  64. return wgtypes.Key{}, errors.New("incorrect seed size")
  65. }
  66. return wgtypes.ParseKey(base64.StdEncoding.EncodeToString(n.point.BytesMontgomery()))
  67. }
  68. // Key.Save : saves the private key to path.
  69. func (n *Key) Save(path string) error {
  70. f, err := os.Create(path)
  71. if err != nil {
  72. return err
  73. }
  74. defer f.Close()
  75. f.Write(n.point.Bytes())
  76. return nil
  77. }
  78. // ReadFrom reads a private key from path.
  79. func ReadFrom(path string) (*Key, error) {
  80. key, err := os.ReadFile(path)
  81. if err != nil {
  82. return nil, err
  83. }
  84. point, err := (&edwards25519.Point{}).SetBytes(key)
  85. if err != nil {
  86. return nil, err
  87. }
  88. return &Key{point}, nil
  89. }
  90. // NewName creates a new pkix.Name with common name, country, and organization
  91. func NewName(commonName, country, org string) pkix.Name {
  92. res := NewCName(commonName)
  93. res.Country = []string{country}
  94. res.Organization = []string{org}
  95. return res
  96. }
  97. // NewCName creates a new pkix.Name with only a common name
  98. func NewCName(commonName string) pkix.Name {
  99. return pkix.Name{
  100. CommonName: commonName,
  101. }
  102. }
  103. // NewCSR creates a new certificate signing request for a
  104. func NewCSR(key ed25519.PrivateKey, name pkix.Name) (*x509.CertificateRequest, error) {
  105. dnsnames := []string{}
  106. dnsnames = append(dnsnames, name.CommonName)
  107. derCertRequest, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
  108. Subject: name,
  109. PublicKey: key.Public(),
  110. DNSNames: dnsnames,
  111. PublicKeyAlgorithm: x509.Ed25519,
  112. Version: 3,
  113. }, key)
  114. if err != nil {
  115. return nil, err
  116. }
  117. csr, err := x509.ParseCertificateRequest(derCertRequest)
  118. if err != nil {
  119. return nil, err
  120. }
  121. return csr, nil
  122. }
  123. // SelfSignedCA returns a new self-signed certificate
  124. func SelfSignedCA(key ed25519.PrivateKey, req *x509.CertificateRequest, days int) (*x509.Certificate, error) {
  125. template := &x509.Certificate{
  126. BasicConstraintsValid: true,
  127. IsCA: true,
  128. Version: req.Version,
  129. KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDataEncipherment,
  130. NotAfter: time.Now().Add(duration(days)),
  131. NotBefore: time.Now(),
  132. SerialNumber: serialNumber(),
  133. PublicKey: key.Public(),
  134. Subject: pkix.Name{
  135. CommonName: req.Subject.CommonName,
  136. Organization: req.Subject.Organization,
  137. Country: req.Subject.Country,
  138. },
  139. }
  140. rootCa, err := x509.CreateCertificate(rand.Reader, template, template, req.PublicKey, key)
  141. if err != nil {
  142. return nil, err
  143. }
  144. result, err := x509.ParseCertificate(rootCa)
  145. if err != nil {
  146. return nil, err
  147. }
  148. return result, nil
  149. }
  150. // NewEndEntityCert issues a new certificate from a parent certificate authority
  151. func NewEndEntityCert(key ed25519.PrivateKey, req *x509.CertificateRequest, parent *x509.Certificate, days int) (*x509.Certificate, error) {
  152. template := &x509.Certificate{
  153. Version: req.Version,
  154. NotBefore: time.Now(),
  155. NotAfter: time.Now().Add(duration(days)),
  156. SerialNumber: serialNumber(),
  157. Subject: req.Subject,
  158. Issuer: parent.Subject,
  159. KeyUsage: x509.KeyUsageDigitalSignature,
  160. BasicConstraintsValid: true,
  161. DNSNames: req.DNSNames,
  162. }
  163. rootCa, err := x509.CreateCertificate(rand.Reader, template, parent, req.PublicKey, key)
  164. if err != nil {
  165. return nil, err
  166. }
  167. result, err := x509.ParseCertificate(rootCa)
  168. if err != nil {
  169. return nil, err
  170. }
  171. return result, nil
  172. }
  173. // SaveRequest saves a certificate request to the specified path
  174. func SaveRequest(path, name string, csr *x509.CertificateRequest) error {
  175. if err := os.MkdirAll(path, 0600); err != nil {
  176. return err
  177. }
  178. requestOut, err := os.Create(path + name)
  179. if err != nil {
  180. return err
  181. }
  182. defer requestOut.Close()
  183. if err := pem.Encode(requestOut, &pem.Block{
  184. Type: "CERTIFICATE REQUEST",
  185. Bytes: csr.Raw,
  186. }); err != nil {
  187. return err
  188. }
  189. return nil
  190. }
  191. // SaveCertToFile save a certificate to the specified path
  192. func SaveCertToFile(path, name string, cert *x509.Certificate) error {
  193. //certbytes, err := x509.ParseCertificate(cert)
  194. if err := os.MkdirAll(path, 0600); err != nil {
  195. return fmt.Errorf("failed to create dir %s %w", path, err)
  196. }
  197. certOut, err := os.Create(path + name)
  198. if err != nil {
  199. return fmt.Errorf("failed to open certficate file for writing: %v", err)
  200. }
  201. defer certOut.Close()
  202. if err := pem.Encode(certOut, &pem.Block{
  203. Type: "CERTIFICATE",
  204. Bytes: cert.Raw,
  205. }); err != nil {
  206. return fmt.Errorf("failed to write certificate to file %v", err)
  207. }
  208. return nil
  209. }
  210. // SaveKeyToFile save a private key (ed25519) to the certs database
  211. func SaveKeyToFile(path, name string, key ed25519.PrivateKey) error {
  212. //func SaveKey(name string, key *ecdsa.PrivateKey) error {
  213. if err := os.MkdirAll(path, 0600); err != nil {
  214. return fmt.Errorf("failed to create dir %s %w", path, err)
  215. }
  216. keyOut, err := os.Create(path + name)
  217. if err != nil {
  218. return fmt.Errorf("failed open key file for writing: %v", err)
  219. }
  220. defer keyOut.Close()
  221. privBytes, err := x509.MarshalPKCS8PrivateKey(key)
  222. if err != nil {
  223. return fmt.Errorf("failedto marshal key %v ", err)
  224. }
  225. if err := pem.Encode(keyOut, &pem.Block{
  226. Type: "PRIVATE KEY",
  227. Bytes: privBytes,
  228. }); err != nil {
  229. return fmt.Errorf("failed to write key to file %v", err)
  230. }
  231. return nil
  232. }
  233. // ReadCertFromFile reads a certificate from disk
  234. func ReadCertFromFile(name string) (*x509.Certificate, error) {
  235. contents, err := os.ReadFile(name)
  236. if err != nil {
  237. return nil, fmt.Errorf("unable to read file %w", err)
  238. }
  239. block, _ := pem.Decode(contents)
  240. if block == nil || block.Type != "CERTIFICATE" {
  241. return nil, errors.New("not a cert " + block.Type)
  242. }
  243. cert, err := x509.ParseCertificate(block.Bytes)
  244. if err != nil {
  245. return nil, fmt.Errorf("unable to parse cert %w", err)
  246. }
  247. return cert, nil
  248. }
  249. // ReadKeyFromFile reads a private key (ed25519) from disk
  250. func ReadKeyFromFile(name string) (*ed25519.PrivateKey, error) {
  251. bytes, err := os.ReadFile(name)
  252. if err != nil {
  253. return nil, fmt.Errorf("unable to read file %w", err)
  254. }
  255. keyBytes, _ := pem.Decode(bytes)
  256. key, err := x509.ParsePKCS8PrivateKey(keyBytes.Bytes)
  257. if err != nil {
  258. return nil, fmt.Errorf("unable to parse file %w", err)
  259. }
  260. private := key.(ed25519.PrivateKey)
  261. return &private, nil
  262. }
  263. // serialNumber generates a serial number for a certificate
  264. func serialNumber() *big.Int {
  265. serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
  266. serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
  267. if err != nil {
  268. return nil
  269. }
  270. return serialNumber
  271. }
  272. // duration coverts the number of days to time.duration
  273. func duration(days int) time.Duration {
  274. hours := days * 24
  275. duration, err := time.ParseDuration(fmt.Sprintf("%dh", hours))
  276. if err != nil {
  277. duration = time.Until(time.Now().Add(time.Hour * 24))
  278. }
  279. return duration
  280. }