github地址 : https://github.com/jiangshengxin/golang-phplaravel-aes256-cbc

  Golang代码
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  
package main
 
import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/base64"
    "encoding/json"
    "errors"
    "strings"
    "github.com/elliotchance/phpserialize"
    "io"
    "bytes"
    "crypto/rand"
    "crypto/hmac"
    "crypto/sha256"
    "fmt"
    "os"
)
 
func main()  {
 
    //加密
    token, err := encode("jiangshengxin")
    if err != nil {
 
    }
    println(token)
    os.Exit(1)
     
    //解密
    str, err := decode("eyJpdiI6IkJLZmJoOTBGa1A0MGRiLy8zemg4c1E9PSIsIm1hYyI6IjAzZDZiZGQ5YWY4NGY2NGZkMTgwMmFjZTFkZWMwNDgzM2I4ZmUyZTUzOTI2OGY5ZjEzNDQ1OGMwMWE2YmYxYzYiLCJ2YWx1ZSI6IlBqQ1llMW81eFlIZUppaEgyQldrdWxpQzNRb3kyaHNCb0hlS1JTTDR0b2s9In0=")
    if err != nil {
 
    }
    println(str)
    os.Exit(2)
 
}
 
 
//加密
func encode(ciphertext string) (string,error) {
 
    //初始化密钥
    key:= []byte("1a04c2a6bl6341639118a9bdbbea545a")
 
    //序列化密文
    ciphertextNew,err := phpserialize.Marshal(ciphertext,nil)
    if err != nil {
        return "",err
    }
    plaintext := []byte(ciphertextNew)
 
    //填充明文至加密要求长度
    /*  paddingCount := aes.BlockSize - len(plaintext)%aes.BlockSize
        if paddingCount != 0 {
            plaintext = append(plaintext, bytes.Repeat([]byte{byte(0)}, paddingCount)...)
        }*/
    plaintext,err = Pad(plaintext,aes.BlockSize)
    if err != nil {
        return "",err
    }
 
    // CBC mode works on blocks so plaintexts may need to be padded to the
    // next whole block. For an example of such padding, see
    // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
    // assume that the plaintext is already of the correct length.
    //检查密文长度是否合法
    /*if len(plaintext)%aes.BlockSize != 0 {
        return "",err
    }*/
 
    block, err := aes.NewCipher(key)
    if err != nil {
        return "",err
    }
 
    // The IV needs to be unique, but not secure. Therefore it's common to
    // include it at the beginning of the ciphertext.
    iv := make([]byte, aes.BlockSize)
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        return "",err
    }
 
    mode := cipher.NewCBCEncrypter(block, iv)
    mode.CryptBlocks(plaintext, plaintext)
 
    //原加密算法
    /*type payload struct {
        IV string
        Value string
        Mac string
    }
    p := payload{}
    p.IV = base64.StdEncoding.EncodeToString(iv)
    p.Value = base64.StdEncoding.EncodeToString(plaintext)
    data, err := json.Marshal(p)*/
    //现在加密算法
    payload := make(map[string]string)
    payload["iv"] = base64.StdEncoding.EncodeToString(iv)
    payload["value"] = base64.StdEncoding.EncodeToString(plaintext)
    //生成mac
    h := hmac.New(sha256.New,[]byte(key))
    io.WriteString(h,payload["iv"]+payload["value"])
    payload["mac"] = fmt.Sprintf("%x", h.Sum(nil))
 
    //转json
    data, err := json.Marshal(payload)
 
    if err != nil {
        return "",err
    }
    ciphertext = base64.StdEncoding.EncodeToString(data)
    return ciphertext,nil
}
 
 
//解密
func decode(ciphertext string) (string, error) {
 
    //初始化密钥
    key:= "1a04c2a6bl6341639118a9bdbbea545a"
 
    decodeBytes, err := base64.StdEncoding.DecodeString(ciphertext)
    if err != nil {
        return "", errors.New("ciphertext value must in base64 format")
    }
    var payload struct {
        IV    string
        Value string
        Mac   string
    }
    err = json.Unmarshal(decodeBytes, &payload)
    if err != nil {
        return "", errors.New("ciphertext value must be valid")
    }
    encryptedText, err := base64.StdEncoding.DecodeString(payload.Value)
    if err != nil {
        return "", errors.New("encrypted text must be valid base64 format")
    }
    iv, err := base64.StdEncoding.DecodeString(payload.IV)
    if err != nil {
        return "", errors.New("iv in payload must be valid base64 format")
    }
    var keyBytes []byte
    if strings.HasPrefix(key, "base64:") {
        keyBytes, err = base64.StdEncoding.DecodeString(string(key[7:]))
        if err != nil {
            return "", errors.New("seems like you provide a key in base64 format, but it's not valid")
        }
    else {
        keyBytes = []byte(key)
    }
    block, err := aes.NewCipher(keyBytes)
    if err != nil {
        return "", err
    }
    mode := cipher.NewCBCDecrypter(block, iv)
    mode.CryptBlocks(encryptedText, encryptedText)
    var cleartext string
    err = phpserialize.Unmarshal(encryptedText, &cleartext)
    return cleartext, nil
}
 
//ase-256-cbc长度填充
func Pad(src []byte, blockSize int) ([]byte, error) {
    // 按标准只允许1 - 255个大小的块.
    if blockSize < 1 || blockSize > 255 {
        return nil, errors.New("pkcs7: block size must be between 1 and 255 inclusive")
    }
 
    // 通过设定目标块大小来计算所需填充的长度
    // 减去源的溢出
    padLen := blockSize - len(src)%blockSize
 
    // 将包含要重复的字节的字节片.
    padding := []byte{byte(padLen)}
 
    // 重复那个字节padLen时间
    padding = bytes.Repeat(padding, padLen)
 
    // 向src追加填充.
    return append(src, padding...), nil
}
 
  


  php-laravel 内置加密类库代码如下
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  
<?php
 
 
 
$aes = new Encrypter();
echo $aes->encrypt('exampleplaintext')."\n";
 
echo $aes->decrypt("eyJpdiI6IkJLZmJoOTBGa1A0MGRiLy8zemg4c1E9PSIsIm1hYyI6IjAzZDZiZGQ5YWY4NGY2NGZkMTgwMmFjZTFkZWMwNDgzM2I4ZmUyZTUzOTI2OGY5ZjEzNDQ1OGMwMWE2YmYxYzYiLCJ2YWx1ZSI6IlBqQ1llMW81eFlIZUppaEgyQldrdWxpQzNRb3kyaHNCb0hlS1JTTDR0b2s9In0=");
 
 
class Encrypter
{
    /**
     * The encryption key.
     *
     * @var string
     */
    protected $key;
 
    /**
     * The algorithm used for encryption.
     *
     * @var string
     */
    protected $cipher;
 
    /**
     * Create a new encrypter instance.
     *
     * @param  string  $key
     * @param  string  $cipher
     * @return void
     *
     * @throws \RuntimeException
     */
    //1e04f2f6bd6341639118a9bdbbae545b
    public function __construct($key = '1a04c2a6bl6341639118a9bdbbea545a', $cipher = 'AES-256-CBC')
    {
        $key = (string) $key;
        if (static::supported($key, $cipher)) {
            $this->key = $key;
            $this->cipher = $cipher;
        else {
            throw new RuntimeException('The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.');
        }
    }
 
    /**
     * Determine if the given key and cipher combination is valid.
     *
     * @param  string  $key
     * @param  string  $cipher
     * @return bool
     */
    public static function supported($key, $cipher)
    {
        $length = mb_strlen($key, '8bit');
        return ($cipher === 'AES-128-CBC' && $length === 16) || ($cipher === 'AES-256-CBC' && $length === 32);
    }
 
    /**
     * Encrypt the given value.
     *
     * @param  string  $value
     * @return string
     *
     * @throws \Illuminate\Contracts\Encryption\EncryptException
     */
    public function encrypt($value)
    {
        $iv = random_bytes(16);
        $value = \openssl_encrypt(serialize($value), $this->cipher, $this->key, 0, $iv);
        if ($value === false) {
            throw new EncryptException('Could not encrypt the data.');
        }
 
        // Once we have the encrypted value we will go ahead base64_encode the input
        // vector and create the MAC for the encrypted value so we can verify its
        // authenticity. Then, we'll JSON encode the data in a "payload" array.
        $mac = $this->hash($iv = base64_encode($iv), $value);
        $json = json_encode(compact('iv', 'value', 'mac'));
 
        if (! is_string($json)) {
            throw new EncryptException('Could not encrypt the data.');
        }
 
        return base64_encode($json);
    }
 
    /**
     * Decrypt the given value.
     *
     * @param  string  $payload
     * @return string
     *
     * @throws \Illuminate\Contracts\Encryption\DecryptException
     */
    public function decrypt($payload)
    {
        $payload = $this->getJsonPayload($payload);
 
        $iv = base64_decode($payload['iv']);
        $decrypted = \openssl_decrypt($payload['value'], $this->cipher, $this->key, 0, $iv);
 
        if ($decrypted === false) {
            throw new DecryptException('Could not decrypt the data.');
        }
 
        return unserialize($decrypted);
    }
 
    /**
     * Create a MAC for the given value.
     *
     * @param  string  $iv
     * @param  string  $value
     * @return string
     */
    protected function hash($iv, $value)
    {
        return hash_hmac('sha256', $iv.$value, $this->key);
    }
 
    /**
     * Get the JSON array from the given payload.
     *
     * @param  string  $payload
     * @return array
     *
     * @throws \Illuminate\Contracts\Encryption\DecryptException
     */
    protected function getJsonPayload($payload)
    {
        $payload = json_decode(base64_decode($payload), true);
        // If the payload is not valid JSON or does not have the proper keys set we will
        // assume it is invalid and bail out of the routine since we will not be able
        // to decrypt the given value. We'll also check the MAC for this encryption.
        if (! $this->validPayload($payload)) {
            throw new DecryptException('The payload is invalid.');
        }
 
        if (! $this->validMac($payload)) {
            throw new DecryptException('The MAC is invalid.');
        }
 
        return $payload;
    }
 
    /**
     * Verify that the encryption payload is valid.
     *
     * @param  mixed  $payload
     * @return bool
     */
    protected function validPayload($payload)
    {
        return is_array($payload) && isset($payload['iv'], $payload['value'], $payload['mac']);
    }
 
    /**
     * Determine if the MAC for the given payload is valid.
     *
     * @param  array  $payload
     * @return bool
     */
    protected function validMac(array $payload)
    {
        $bytes = random_bytes(16);
 
        $calcMac = hash_hmac('sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true);
        return hash_equals(hash_hmac('sha256', $payload['mac'], $bytes, true), $calcMac);
    }
 
    /**
     * Get the encryption key.
     *
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }
}
 
 
  

 

---------------------------------------------------------------------------------------------
不忘初心 方得始终!

唯有志存高远,方能风行天下。

道之所存,虽千万人吾往矣! 情之所钟,虽千万里吾念矣~

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。