1
0
mirror of https://github.com/fumiama/aes-rsa-tcp-demo.git synced 2026-06-05 01:20:24 +08:00
Files
aes-rsa-tcp-demo/utils/rsa.go
源文雨 f79b275f42 init
2023-12-29 16:29:41 +09:00

57 lines
1.6 KiB
Go

package utils
import (
"crypto/rsa"
"encoding/binary"
"errors"
"hash/crc64"
"math"
_ "unsafe"
)
//go:linkname encrypt crypto/rsa.encrypt
func encrypt(pub *rsa.PublicKey, plaintext []byte) ([]byte, error)
//go:linkname decrypt crypto/rsa.decrypt
func decrypt(priv *rsa.PrivateKey, ciphertext []byte, check bool) ([]byte, error)
// RSAPrivateKeyEncrypt use the method generally in sign
func RSAPrivateKeyEncrypt(priv *rsa.PrivateKey, plaintext []byte) ([]byte, error) {
if len(plaintext) > math.MaxUint16 {
return nil, errors.New("plaintext too large")
}
h := crc64.New(crc64.MakeTable(crc64.ECMA))
_, err := h.Write(plaintext)
if err != nil {
return nil, err
}
data := make([]byte, len(plaintext)+8+2)
n := copy(data[:], plaintext)
binary.LittleEndian.PutUint64(data[n:n+8], h.Sum64())
binary.LittleEndian.PutUint16(data[n+8:n+8+2], uint16(len(plaintext)))
return decrypt(priv, data, false)
}
// RSAPublicKeyDecrypt use the method generally in sign
func RSAPublicKeyDecrypt(pub *rsa.PublicKey, ciphertext []byte) ([]byte, error) {
data, err := encrypt(pub, ciphertext)
if err != nil {
return nil, err
}
n := binary.LittleEndian.Uint16(data[len(data)-2:])
p := len(data) - int(n) - 8 - 2
if p < 0 || p > len(data) {
return nil, errors.New("invalid ciphertext length")
}
data = data[p:]
h := crc64.New(crc64.MakeTable(crc64.ECMA))
_, err = h.Write(data[:len(data)-8-2])
if err != nil {
return nil, err
}
if h.Sum64() != binary.LittleEndian.Uint64(data[len(data)-8-2:len(data)-2]) {
return nil, errors.New("invalid ciphertext")
}
return data[:len(data)-8-2], nil
}