tls.go 7.2 KB

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