tls.go 7.8 KB

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