crypto.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package crypto
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "encoding/base64"
  7. "encoding/json"
  8. "encoding/pem"
  9. "fmt"
  10. "time"
  11. "github.com/0xJacky/Nginx-UI/internal/cache"
  12. "github.com/uozi-tech/cosy/logger"
  13. )
  14. const (
  15. CacheKey = "crypto"
  16. timeout = 10 * time.Minute
  17. )
  18. type Params struct {
  19. PrivateKey string `json:"-"`
  20. PublicKey string `json:"public_key"`
  21. }
  22. // GenerateRSAKeyPair generates a new RSA key pair
  23. func GenerateRSAKeyPair() (privateKeyPEM, publicKeyPEM []byte, err error) {
  24. privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
  25. if err != nil {
  26. return nil, nil, err
  27. }
  28. privateKeyPEM = pem.EncodeToMemory(&pem.Block{
  29. Type: "RSA PRIVATE KEY",
  30. Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
  31. })
  32. publicKeyPEM = pem.EncodeToMemory(&pem.Block{
  33. Type: "RSA PUBLIC KEY",
  34. Bytes: x509.MarshalPKCS1PublicKey(&privateKey.PublicKey),
  35. })
  36. return
  37. }
  38. // GetCryptoParams registers a new key pair in the cache if it doesn't exist
  39. // otherwise, it returns the existing nonce and public key
  40. func GetCryptoParams() (params *Params, err error) {
  41. // Check if the key pair exists in then cache
  42. if value, ok := cache.Get(CacheKey); ok {
  43. return value.(*Params), nil
  44. }
  45. // Generate a nonce = hash(publicKey)
  46. privateKeyPEM, publicKeyPEM, err := GenerateRSAKeyPair()
  47. if err != nil {
  48. return nil, err
  49. }
  50. params = &Params{
  51. PrivateKey: string(privateKeyPEM),
  52. PublicKey: string(publicKeyPEM),
  53. }
  54. cache.Set(CacheKey, params, timeout)
  55. return
  56. }
  57. // Decrypt decrypts the data with the private key (nonce, paramEncrypted)
  58. func Decrypt(paramEncrypted string) (data map[string]interface{}, err error) {
  59. // Get crypto params from cache
  60. value, ok := cache.Get(CacheKey)
  61. if !ok {
  62. return nil, ErrTimeout
  63. }
  64. params := value.(*Params)
  65. block, _ := pem.Decode([]byte(params.PrivateKey))
  66. if block == nil {
  67. return nil, fmt.Errorf("failed to decode PEM block containing private key")
  68. }
  69. privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  70. if err != nil {
  71. logger.Errorf("failed to parse private key: %v", err)
  72. return nil, err
  73. }
  74. paramEncryptedDecoded, err := base64.StdEncoding.DecodeString(paramEncrypted)
  75. if err != nil {
  76. logger.Errorf("base64 decode error: %v", err)
  77. return nil, err
  78. }
  79. decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, paramEncryptedDecoded)
  80. if err != nil {
  81. logger.Errorf("decryption failed: %v", err)
  82. return nil, err
  83. }
  84. err = json.Unmarshal(decrypted, &data)
  85. if err != nil {
  86. return nil, err
  87. }
  88. return
  89. }