148 lines
2.9 KiB
Go
148 lines
2.9 KiB
Go
package src
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/cipher"
|
|
"crypto/des"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"github.com/gin-gonic/gin"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strconv"
|
|
)
|
|
|
|
func InitHttpServer(host string, port int) {
|
|
|
|
log.Println("Start http server, Listen " + strconv.Itoa(port))
|
|
h := gin.Default()
|
|
h.GET("/api/v1/refresh", refreshCert)
|
|
h.GET("/api/v1/cert", getCert)
|
|
err := h.Run(host + ":" + strconv.Itoa(port))
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
func getCert(c *gin.Context) {
|
|
name := c.Param("name")
|
|
token := getToken(c)
|
|
|
|
dir := GetAppConfig().CertDir
|
|
dir = filepath.Join(dir, name)
|
|
_, err := os.Stat(dir)
|
|
if os.IsNotExist(err) {
|
|
c.JSON(200, gin.H{
|
|
"code": 500,
|
|
"msg": "Name does not exist.",
|
|
})
|
|
return
|
|
}
|
|
crtFilePath := path.Join(dir, CertFileName)
|
|
crtContent, err := os.ReadFile(crtFilePath)
|
|
if err != nil {
|
|
c.JSON(200, gin.H{
|
|
"code": 500,
|
|
"msg": "Failed to read crt file.",
|
|
})
|
|
return
|
|
}
|
|
crt := string(crtContent)
|
|
|
|
keyFilePath := path.Join(dir, KeyFileName)
|
|
keyContent, err := os.ReadFile(keyFilePath)
|
|
if err != nil {
|
|
c.JSON(200, gin.H{
|
|
"code": 500,
|
|
"msg": "Failed to read key file.",
|
|
})
|
|
return
|
|
}
|
|
key := string(keyContent)
|
|
|
|
c.JSON(200, gin.H{
|
|
"code": 200,
|
|
"msg": "Success",
|
|
"data": gin.H{
|
|
"crt": encryptResult(crt, token),
|
|
"key": encryptResult(key, token),
|
|
},
|
|
})
|
|
}
|
|
|
|
func refreshCert(c *gin.Context) {
|
|
name := c.Param("name")
|
|
domain := GetAppConfig().FindDomain(name)
|
|
if domain == nil {
|
|
c.JSON(200, gin.H{
|
|
"code": 500,
|
|
"msg": "Name does not exist.",
|
|
})
|
|
return
|
|
}
|
|
Apply(*domain)
|
|
c.JSON(200, gin.H{
|
|
"code": 200,
|
|
"msg": "Success",
|
|
})
|
|
}
|
|
|
|
func getToken(c *gin.Context) (token string) {
|
|
token = decryptParam(c.Param("token"))
|
|
return
|
|
}
|
|
|
|
func decryptParam(param string) string {
|
|
priKey := GetAppConfig().Encrypt.PriKey
|
|
|
|
// 使用RSA解密
|
|
block, _ := pem.Decode([]byte(priKey))
|
|
if block == nil {
|
|
log.Fatal("failed to parse PEM block containing the private key")
|
|
}
|
|
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
paramData := []byte(param)
|
|
plaintext, err := rsa.DecryptPKCS1v15(nil, privateKey, paramData)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return string(plaintext)
|
|
}
|
|
|
|
func encryptResult(content string, token string) string {
|
|
key := []byte(token)
|
|
plaintext := []byte(content)
|
|
|
|
block, err := des.NewCipher(key)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
plaintext = pad(plaintext, block.BlockSize())
|
|
|
|
iv := make([]byte, block.BlockSize())
|
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
|
log.Fatal("Error generating random IV:", err)
|
|
}
|
|
mode := cipher.NewCBCEncrypter(block, iv)
|
|
|
|
ciphertext := make([]byte, len(plaintext))
|
|
mode.CryptBlocks(ciphertext, plaintext)
|
|
|
|
return string(ciphertext)
|
|
}
|
|
|
|
func pad(src []byte, blockSize int) []byte {
|
|
padding := blockSize - len(src)%blockSize
|
|
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
return append(src, padText...)
|
|
}
|