tls.go 8.0 KB

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