key.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package models
  2. import (
  3. "crypto/ed25519"
  4. "crypto/rand"
  5. "encoding/base64"
  6. "errors"
  7. "os"
  8. "filippo.io/edwards25519"
  9. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  10. )
  11. type (
  12. Key struct {
  13. point *edwards25519.Point
  14. }
  15. )
  16. // Generates a new key.
  17. func NewKey() (*Key, error) {
  18. seed := make([]byte, 64)
  19. rand.Reader.Read(seed)
  20. s, err := (&edwards25519.Scalar{}).SetUniformBytes(seed)
  21. if err != nil {
  22. return nil, err
  23. }
  24. return &Key{(&edwards25519.Point{}).ScalarBaseMult(s)}, nil
  25. }
  26. // Returns the private key in Edwards form used for EdDSA.
  27. func (n *Key) Ed25519PrivateKey() (ed25519.PrivateKey, error) {
  28. if n.point == nil {
  29. return ed25519.PrivateKey{}, errors.New("nil point")
  30. }
  31. if len(n.point.Bytes()) != ed25519.SeedSize {
  32. return ed25519.PrivateKey{}, errors.New("incorrect seed size")
  33. }
  34. return ed25519.NewKeyFromSeed(n.point.Bytes()), nil
  35. }
  36. // Returns the private key in Montogomery form used for ECDH.
  37. func (n *Key) Curve25519PrivateKey() (wgtypes.Key, error) {
  38. if n.point == nil {
  39. return wgtypes.Key{}, errors.New("nil point")
  40. }
  41. if len(n.point.Bytes()) != ed25519.SeedSize {
  42. return wgtypes.Key{}, errors.New("incorrect seed size")
  43. }
  44. return wgtypes.ParseKey(base64.StdEncoding.EncodeToString(n.point.BytesMontgomery()))
  45. }
  46. // Saves the private key to path.
  47. func (n *Key) Save(path string) error {
  48. f, err := os.Create(path)
  49. if err != nil {
  50. return err
  51. }
  52. defer f.Close()
  53. f.Write(n.point.Bytes())
  54. return nil
  55. }
  56. // Reads the private key from path.
  57. func ReadFrom(path string) (*Key, error) {
  58. key, err := os.ReadFile(path)
  59. if err != nil {
  60. return nil, err
  61. }
  62. point, err := (&edwards25519.Point{}).SetBytes(key)
  63. if err != nil {
  64. return nil, err
  65. }
  66. return &Key{point}, nil
  67. }