| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package utils
- import (
- "crypto"
- "crypto/aes"
- "crypto/cipher"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha256"
- "crypto/x509"
- "encoding/base64"
- "encoding/pem"
- "fmt"
- "io"
- )
- // https://stackoverflow.com/questions/23897809/different-results-in-go-and-pycrypto-when-using-aes-cfb
- // CFB stream with 8 bit segment size
- // See http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
- type cfb8 struct {
- b cipher.Block
- blockSize int
- in []byte
- out []byte
- decrypt bool
- }
- func (x *cfb8) XORKeyStream(dst, src []byte) {
- for i := range src {
- x.b.Encrypt(x.out, x.in)
- copy(x.in[:x.blockSize-1], x.in[1:])
- if x.decrypt {
- x.in[x.blockSize-1] = src[i]
- }
- dst[i] = src[i] ^ x.out[0]
- if !x.decrypt {
- x.in[x.blockSize-1] = dst[i]
- }
- }
- }
- // NewCFB8Encrypter returns a Stream which encrypts with cipher feedback mode
- // (segment size = 8), using the given Block. The iv must be the same length as
- // the Block's block size.
- func newCFB8Encrypter(block cipher.Block, iv []byte) cipher.Stream {
- return newCFB8(block, iv, false)
- }
- // NewCFB8Decrypter returns a Stream which decrypts with cipher feedback mode
- // (segment size = 8), using the given Block. The iv must be the same length as
- // the Block's block size.
- func newCFB8Decrypter(block cipher.Block, iv []byte) cipher.Stream {
- return newCFB8(block, iv, true)
- }
- func newCFB8(block cipher.Block, iv []byte, decrypt bool) cipher.Stream {
- blockSize := block.BlockSize()
- if len(iv) != blockSize {
- // stack trace will indicate whether it was de or encryption
- panic("cipher.newCFB: IV length must equal block size")
- }
- x := &cfb8{
- b: block,
- blockSize: blockSize,
- out: make([]byte, blockSize),
- in: make([]byte, blockSize),
- decrypt: decrypt,
- }
- copy(x.in, iv)
- return x
- }
- func toAESKey(key string) []byte {
- k := []byte(key)
- if len(k) > 32 {
- return k[0:32]
- } else {
- for len(k) < 32 {
- k = append(k, '$')
- }
- return k
- }
- }
- func descryptAES(k, secret []byte) ([]byte, error) {
- block, err := aes.NewCipher(k)
- if err != nil {
- return nil, err
- }
- if len(secret) < aes.BlockSize {
- return nil, fmt.Errorf("ciphertext too short")
- }
- iv := secret[:aes.BlockSize]
- ciphertext := secret[aes.BlockSize:]
- stream := newCFB8Decrypter(block, iv)
- stream.XORKeyStream(ciphertext, ciphertext)
- return ciphertext, nil
- }
- func encryptAES(k, msg []byte) ([]byte, error) {
- block, err := aes.NewCipher(k)
- if err != nil {
- return nil, err
- }
- cipherText := make([]byte, aes.BlockSize+len(msg))
- iv := cipherText[:aes.BlockSize]
- if _, err = io.ReadFull(rand.Reader, iv); err != nil {
- return nil, err
- }
- stream := newCFB8Encrypter(block, iv)
- stream.XORKeyStream(cipherText[aes.BlockSize:], msg)
- return cipherText, nil
- }
- func DescryptAESBase64(key, secret string) (string, error) {
- s, e := base64.StdEncoding.DecodeString(secret)
- if e != nil {
- return "", e
- }
- k := toAESKey(key)
- result, e := descryptAES(k, s)
- if e != nil {
- return "", e
- }
- return string(result), nil
- }
- func DescryptAESBase64Url(key, secret string) (string, error) {
- s, e := base64.URLEncoding.DecodeString(secret)
- if e != nil {
- return "", e
- }
- k := toAESKey(key)
- result, e := descryptAES(k, s)
- if e != nil {
- return "", e
- }
- return string(result), nil
- }
- func EncryptAESBase64(key, msg string) (string, error) {
- k := toAESKey(key)
- result, err := encryptAES(k, []byte(msg))
- if err != nil {
- return "", err
- }
- return base64.StdEncoding.EncodeToString(result), nil
- }
- func EncryptAESBase64Url(key, msg string) (string, error) {
- k := toAESKey(key)
- result, err := encryptAES(k, []byte(msg))
- if err != nil {
- return "", err
- }
- return base64.URLEncoding.EncodeToString(result), nil
- }
- // RSA 加密
- func rsaEncrypt(publicKey, origData []byte) ([]byte, error) {
- block, _ := pem.Decode(publicKey)
- if block == nil {
- return nil, fmt.Errorf("public key error")
- }
- pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
- if err != nil {
- return nil, err
- }
- pub := pubInterface.(*rsa.PublicKey)
- return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
- }
- // Base64封装的 RSA 密文解密
- func RsaEncryptBase64(publicKey []byte, origData string) (string, error) {
- data := []byte(origData)
- s, e := rsaEncrypt(publicKey, data)
- if e != nil {
- return "", e
- }
- result := base64.StdEncoding.EncodeToString(s)
- return string(result), nil
- }
- // RSA 解密
- func rsaDecrypt(privateKey, secret []byte) ([]byte, error) {
- block, _ := pem.Decode(privateKey)
- if block == nil {
- return nil, fmt.Errorf("private key error!")
- }
- priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
- if err != nil {
- return nil, err
- }
- return rsa.DecryptPKCS1v15(rand.Reader, priv, secret)
- }
- // Base64封装的 RSA 密文解密
- func RsaDecryptBase64(privateKey []byte, secret string) (string, error) {
- s, e := base64.StdEncoding.DecodeString(secret)
- if e != nil {
- return "", e
- }
- result, e := rsaDecrypt(privateKey, s)
- if e != nil {
- return "", e
- }
- return string(result), nil
- }
- // RSA 签名
- func RsaSign(privateKey []byte, message string) (string, error) {
- block, _ := pem.Decode(privateKey)
- if block == nil {
- return "", fmt.Errorf("private key error!")
- }
- priv, e := x509.ParsePKCS1PrivateKey(block.Bytes)
- if e != nil {
- return "", e
- }
- h := sha256.New()
- h.Write([]byte(message))
- d := h.Sum(nil)
- sign, e := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA256, d)
- return string(sign), e
- }
- // RSA 签名验证
- func RsaUnsign(publicKey []byte, message, sign string) error {
- block, _ := pem.Decode(publicKey)
- if block == nil {
- return fmt.Errorf("private key error!")
- }
- pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
- if err != nil {
- return err
- }
- pub := pubInterface.(*rsa.PublicKey)
- h := sha256.New()
- h.Write([]byte(message))
- d := h.Sum(nil)
- return rsa.VerifyPKCS1v15(pub, crypto.SHA256, d, []byte(sign))
- }
|