最近更新时间:

说明

  1. 主要用于隐私数据加密
  2. 使用128/256位ECB模式的AES加密算法
  3. 密钥联系技术支持获取(AES128密钥和AES256密钥不同,使用不同加密时记得获取相应的密钥)

注:对于外部出行人新增/修改接口不采用整体加密传输时只可采用AES128加密,密钥特殊,需单独申请


算法实现

php版本

AES128

<?php

class Aes
{
    /**
     * @desc aes加密
     *
     * @param $input  明文
     * @param $key    密钥
     * @return string 密文
     */
    public function encrypt($input, $key)
    {
        $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
        $input = $this->pkcs5_pad($input, $size);
        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
        $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $key, $iv);
        $data = mcrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        $data = base64_encode($data);
        return $data;
    }

    /**
     * @desc aes解密
     *
     * @param $cipher 密文
     * @param $key    密钥
     * @return bool|string 密文
     */
    public function decrypt($cipher, $key)
    {
        $decrypted= mcrypt_decrypt(
            MCRYPT_RIJNDAEL_128,
            $key,
            base64_decode($cipher),
            MCRYPT_MODE_ECB
        );
        $dec_s = strlen($decrypted);
        $padding = ord($decrypted[$dec_s-1]);
        $decrypted = substr($decrypted, 0, -$padding);
        return $decrypted;
    }

    private function pkcs5_pad ($text, $blocksize)
    {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }
}

AES256

<?php

interface EncryptionStrategy {
    public function encrypt($data, $key);
    public function decrypt($encryptedData, $key);
}


class Aes256EncryptionStrategyImpl implements EncryptionStrategy {

    private $cipher = 'AES-256-ECB';

    /**
     * 加密方法
     * @param string $data 要加密的明文
     * @param string $key 256 位(32 字节)的加密密钥
     * @return string 加密并经过 Base64 编码后的密文
     */
    public function encrypt($data, $key) {
        // 检查密钥长度是否为 32 字节(256 位)
        $keyBytes = hex2bin($key);
        if (strlen($keyBytes) !== 32) {
            throw new \InvalidArgumentException('Key must be 32 bytes (256 bits) long.');
        }
        // 执行加密操作,使用 OPENSSL_RAW_DATA 确保返回原始二进制数据
        $encrypted = openssl_encrypt($data, $this->cipher, (string)$keyBytes, OPENSSL_RAW_DATA);
        // 对加密后的二进制数据进行 Base64 编码
        return $this->base64UrlEncode($encrypted);
    }

    /**
     * 解密方法
     * @param string $encryptedData 经过 Base64 编码的密文
     * @param string $key 256 位(32 字节)的解密密钥
     * @return string 解密后的明文
     */
    public function decrypt($encryptedData, $key) {
        // 检查密钥长度是否为 32 字节(256 位)
        $keyBytes = hex2bin($key);
        if (strlen($keyBytes) !== 32) {
            throw new \InvalidArgumentException('Key must be 32 bytes (256 bits) long.');
        }
        // 对 Base64 编码的密文进行解码
        $decodedCiphertext = $this->base64UrlDecode($encryptedData);
        // 执行解密操作
        return openssl_decrypt($decodedCiphertext, $this->cipher, (string)$keyBytes, OPENSSL_RAW_DATA);
    }

    function base64UrlEncode($data) {
        // 标准 Base64 编码
        $base64Encoded = base64_encode($data);
        // 保留 = 号
        return strtr($base64Encoded, '+/', '-_');
    }

    function base64UrlDecode($data) {
        // 替换 - 和 _
        $base64Encoded = strtr($data, '-_', '+/');
        // 标准 Base64 解码
        return base64_decode($base64Encoded);
    }

}

go版本

AES128

package helper

import (
	"encoding/base64"
	"errors"
	"fmt"
)

// Decrypt AES PKC#7解密
func Base64AESDecrypt(secretKey, ciphertext string) (response string, err error) {
	defer func() {
		if rErr := recover();rErr != nil{
			err = errors.New(fmt.Sprintf("解密失败panic-%v",rErr))
			//log.Trace.Errorf(context.Background(),consts.DL_TAG_PANIC_RECOVER,"msg=%v-%s",rErr,string(debug.Stack()))
		}
	}()
	enc, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		// todo log
		return
	}

	// ECB解密
	origin, err := AesDecrypt(enc, []byte(secretKey))
	if err != nil {
		// todo log
		return
	}

	// 使用PKCS#7对解密后的内容去除填充
	response = string(PKCS7UnPadding(origin))
	return
}

// Encrypt AES PKC#7解密
func Base64AESEncrypt(secretKey, content string) (response string, err error) {
	defer func() {
		if rErr := recover();rErr != nil{
			err = errors.New(fmt.Sprintf("加密失败panic-%v",rErr))
			//log.Trace.Errorf(context.Background(),consts.DL_TAG_PANIC_RECOVER,"msg=%v-%s",rErr,string(debug.Stack()))
		}
	}()
	//使用PKCS#7对原文进行填充,BlockSize为16字节
	ciphertext := PKCS7Padding([]byte(content), 16)

	//ECB加密
	crypted, err := AesEncrypt(ciphertext, []byte(secretKey))
	if err != nil {
		// todo log
		return
	}

	response = base64.StdEncoding.EncodeToString(crypted)
	return
}
package helper

// AES 解密逻辑处理
import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"errors"
)

// AesEncrypt Aes/ECB模式的加密方法,PKCS7填充方式
func AesEncrypt(src, key []byte) ([]byte, error) {
	Block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(src) == 0 {
		return nil, errors.New("plaintext empty")
	}
	mode := NewECBEncrypter(Block)
	ciphertext := src
	mode.CryptBlocks(ciphertext, ciphertext)
	return ciphertext, nil
}

// AesDecrypt Aes/ECB模式的解密方法,PKCS7填充方式
func AesDecrypt(src, key []byte) ([]byte, error) {
	Block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(src) == 0 {
		return nil, errors.New("plaintext empty")
	}
	mode := NewECBDecrypter(Block)
	ciphertext := src
	mode.CryptBlocks(ciphertext, ciphertext)
	return ciphertext, nil
}

// ECB模式结构体
type ecb struct {
	b         cipher.Block
	blockSize int
}

// 实例化ECB对象
func newECB(b cipher.Block) *ecb {
	return &ecb{
		b:         b,
		blockSize: b.BlockSize(),
	}
}

// ECB加密类
type ecbEncrypter ecb

func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
	return (*ecbEncrypter)(newECB(b))
}

func (x *ecbEncrypter) BlockSize() int {
	return x.blockSize
}

func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.blockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/cipher: output smaller than input")
	}
	for len(src) > 0 {
		x.b.Encrypt(dst, src[:x.blockSize])
		dst = dst[x.blockSize:]
		src = src[x.blockSize:]
	}
}

// ECB解密类
type ecbDecrypter ecb

func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
	return (*ecbDecrypter)(newECB(b))
}

func (x *ecbDecrypter) BlockSize() int {
	return x.blockSize
}

func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.blockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/cipher: output smaller than input")
	}
	for len(src) > 0 {
		x.b.Decrypt(dst, src[:x.blockSize])
		dst = dst[x.blockSize:]
		src = src[x.blockSize:]
	}
}

// PKCS7Padding PKCS7填充
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

// PKCS7UnPadding PKCS7去除
func PKCS7UnPadding(ciphertext []byte) []byte {
	length := len(ciphertext)
	unpadding := int(ciphertext[length-1])
	return ciphertext[:(length - unpadding)]
}

// ZerosPadding 零点填充
func ZerosPadding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(0)}, padding)
	return append(ciphertext, padtext...)
}

// ZerosUnPadding 零点去除
func ZerosUnPadding(ciphertext []byte) []byte {
	return bytes.TrimFunc(ciphertext, func(r rune) bool {
		return r == rune(0)
	})
}

AES256



java版本

请确认jdk在1.8.0_212版本之后,1.8.0_212版本之前会存在强制校验密钥长度的情况,此代码会报非法的密钥长度。

AES128

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AesHelper {

  private static final String ALGORITHM = "AES/ECB/PKCS5Padding";

  /**
   * AES加密
   *
   * @param input 明文
   * @param key   密钥
   * @return 密文
   * @throws Exception
   */
  public static String encrypt(String input, String key) throws Exception {
    SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
    Cipher cipher = Cipher.getInstance(ALGORITHM);
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);
    byte[] encrypted = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
    return Base64.getEncoder().encodeToString(encrypted);
  }

  /**
   * AES解密
   *
   * @param cipher 密文
   * @param key    密钥
   * @return 明文
   * @throws Exception
   */
  public static String decrypt(String cipher, String key) throws Exception {
    SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
    Cipher decipher = Cipher.getInstance(ALGORITHM);
    decipher.init(Cipher.DECRYPT_MODE, secretKey);
    byte[] decrypted = decipher.doFinal(Base64.getDecoder().decode(cipher));
    return new String(decrypted, StandardCharsets.UTF_8).trim();
  }


  public static void main(String[] args) {
    try {
      String key = "g4hh9cc33a969b610b05ed0e004d4e52";
      String originalText = "312984412739843123";

      String encryptedText = encrypt(originalText, key);
      System.out.println("Encrypted: " + encryptedText);

      String decryptedText = decrypt(encryptedText, key);
      System.out.println("Decrypted: " + decryptedText);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

AES256

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Aes256Helper {

  private static final String ALGORITHM = "AES/ECB/PKCS5Padding";

  public static String encrypt(String data, String hexKey) {
    try {
      // 十六进制转字节数组
      byte[] keyBytes = hexToBytes(hexKey);

      // 验证密钥长度
      if (keyBytes.length != 32) {
        throw new IllegalArgumentException("Key must be 32 bytes (256 bits) long.");
      }

      // 初始化加密器
      SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
      Cipher cipher = Cipher.getInstance(ALGORITHM);
      cipher.init(Cipher.ENCRYPT_MODE, secretKey);

      // 执行加密
      byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

      // URL安全Base64编码
      return base64UrlEncode(encrypted);
    } catch (Exception e) {
      throw new RuntimeException("Encryption failed", e);
    }
  }

  public static String decrypt(String encryptedData, String hexKey) {
    try {
      // 十六进制转字节数组
      byte[] keyBytes = hexToBytes(hexKey);

      // 验证密钥长度
      if (keyBytes.length != 32) {
        throw new IllegalArgumentException("Key must be 32 bytes (256 bits) long.");
      }

      // Base64解码
      byte[] decoded = base64UrlDecode(encryptedData);

      // 初始化解密器
      SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
      Cipher cipher = Cipher.getInstance(ALGORITHM);
      cipher.init(Cipher.DECRYPT_MODE, secretKey);
      // 执行解密
      byte[] decrypted = cipher.doFinal(decoded);
      return new String(decrypted, StandardCharsets.UTF_8).trim();
    } catch (Exception e) {
      throw new RuntimeException("Decryption failed", e);
    }

  }

  // Java密钥处理(与PHP的hex2bin对应)
  public static byte[] hexToBytes(String hex) {
    if (hex.length() % 2 != 0) {
      throw new IllegalArgumentException();
    }
    byte[] bytes = new byte[hex.length() / 2];
    for (int i = 0; i < hex.length(); i += 2) {
      bytes[i/2] = (byte) Integer.parseInt(hex.substring(i, i+2), 16);
    }
    return bytes;
  }

  // 编码:替换 +/ 为 -_,保留 =
  private static String base64UrlEncode(byte[] data) {
    String base64 = Base64.getEncoder().encodeToString(data);
    return base64.replace('+', '-').replace('/', '_');
  }

  // 解码:替换 -_ 为 +/,自动补全 =
  private static byte[] base64UrlDecode(String input) {
    String replaced = input.replace('-', '+').replace('_', '/');
    // 补全缺失的 = 号(兼容 Java 8)
    int padding = (4 - (replaced.length() % 4)) % 4;
    StringBuilder sb = new StringBuilder(replaced);
    for (int i = 0; i < padding; i++) {
      sb.append('=');
    }
    return Base64.getDecoder().decode(sb.toString());
  }

  public static void main(String[] args) {
    // 测试用例
    String hexKey = "0495ad3bc8f9e8e9d425fde24af5ca03225465ef37e242c6243df32baf79f48e";
    String original = "ent=2&companyId=1125909874810584&company_id=1125909874810584&timestamp=1741774912437&offset=0&length=100";

    // 加密
    String encrypted = encrypt(original, hexKey);
    System.out.println("加密结果: " + encrypted); // 例如:JzETiB6sW8R3wKwN...

    // 解密
    String decrypted = decrypt(encrypted, hexKey);
    System.out.println("解密结果: " + decrypted); // 应与原始输入相同
  }

}


Go版本

AES 128

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"errors"
	"reflect"
	"strings"
    "testing"
)

type AesTool struct {
	key string
}

func NewAESTool(k string) *AesTool {
	return &AesTool{
		key: k,
	}
}
func (a *AesTool) ECBEncrypt128(data interface{}) (s string, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = errors.New(e.(string))
		}
	}()
	if data == nil {
		return "", nil
	}
	// 类型转换处理器
	var src []byte
	switch v := data.(type) {
	case []byte:
		src = v 
	case string:
		src = []byte(v) 
	default:
		rv := reflect.Indirect(reflect.ValueOf(v))
		if rv.Kind() == reflect.Struct {
			jsonData, err := json.Marshal(v)
			if err != nil {
				return "", errors.New("json序列化失败")
			}
			src = jsonData
		} else {
			return "", errors.New("不支持的数据类型")
		}
	}
	keyBytes, err := GenerateSecretKeyBytes(1, a.key)
	if err != nil {
		return "", err
	}

	ciphertext := PKCS7Padding([]byte(src), 16)

	//ECB加密
	crypted, err := AesEncrypt(ciphertext, keyBytes)
	if err != nil {
		return "", err
	}

	response := base64.StdEncoding.EncodeToString(crypted)
	return response, nil
}

func (a *AesTool) ECBDecrypt128(src string) (s string, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = errors.New(e.(string))
		}
	}()
	replacer := strings.NewReplacer("/", "_", "+", "-")
	src = replacer.Replace(src)
	// 自动补全填充符
	if len(src)%4 != 0 {
		src += strings.Repeat("=", (4-len(src)%4)%4)
	}
	enc, err := base64.URLEncoding.DecodeString(src)
	if err != nil {
		return "", err
	}
	keyBytes, err := GenerateSecretKeyBytes(1, a.key)
	if err != nil {
		return "", err
	}
	// ECB解密
	origin, err := AesDecrypt(enc, []byte(keyBytes))
	if err != nil {
		return "", err
	}

	// 使用PKCS#7对解密后的内容去除填充
	response := string(PKCS7UnPadding(origin))
	return response, nil
}

func AesEncrypt(src, key []byte) ([]byte, error) {
	Block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(src) == 0 {
		return nil, errors.New("plaintext empty")
	}
	mode := NewECBEncrypter(Block)
	ciphertext := src
	mode.CryptBlocks(ciphertext, ciphertext)
	return ciphertext, nil
}

// AesDecrypt Aes/ECB模式的解密方法,PKCS7填充方式
func AesDecrypt(src, key []byte) ([]byte, error) {
	Block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(src) == 0 {
		return nil, errors.New("plaintext empty")
	}
	mode := NewECBDecrypter(Block)
	ciphertext := src
	mode.CryptBlocks(ciphertext, ciphertext)
	return ciphertext, nil
}

// ECB模式结构体
type ecb struct {
	b         cipher.Block
	blockSize int
}

// 实例化ECB对象
func newECB(b cipher.Block) *ecb {
	return &ecb{
		b:         b,
		blockSize: b.BlockSize(),
	}
}

// ECB加密类
type ecbEncrypter ecb

func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
	return (*ecbEncrypter)(newECB(b))
}

func (x *ecbEncrypter) BlockSize() int {
	return x.blockSize
}

func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.blockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/cipher: output smaller than input")
	}
	for len(src) > 0 {
		x.b.Encrypt(dst, src[:x.blockSize])
		dst = dst[x.blockSize:]
		src = src[x.blockSize:]
	}
}

// ECB解密类
type ecbDecrypter ecb

func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
	return (*ecbDecrypter)(newECB(b))
}

func (x *ecbDecrypter) BlockSize() int {
	return x.blockSize
}

func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.blockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/cipher: output smaller than input")
	}
	for len(src) > 0 {
		x.b.Decrypt(dst, src[:x.blockSize])
		dst = dst[x.blockSize:]
		src = src[x.blockSize:]
	}
}

// PKCS7Padding PKCS7填充
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

// PKCS7UnPadding PKCS7去除
func PKCS7UnPadding(ciphertext []byte) []byte {
	length := len(ciphertext)
	unpadding := int(ciphertext[length-1])
	step := length - unpadding
	if step < 0 {
		return []byte{}
	}
	return ciphertext[:step]
}

// GenerateSecretKeyBytes 生成符合AES标准的密钥 ent=0返回空字符串,ent=1使用MD5(128bit),ent=2使用SHA256(256bit)
func GenerateSecretKeyBytes(ent int64, key string) ([]byte, error) {
	switch ent {
	case 0:
		return []byte{}, nil
	case 1:
		return []byte(key), nil
	case 2:
		return HexToBin(key)
	default:
		return nil, errors.New("生成秘钥失败:ent只能是0、1、2")
	}
}

func HexToBin(hexStr string) ([]byte, error) {
	if len(hexStr)%2 != 0 {
		return nil, errors.New("密钥长度必须是128或者256")
	}
	binData, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, errors.New("密钥长度必须是128或者256")
	}
	return binData, nil
}

//单测用例
func TestAesTool_ECBEncrypt128(t *testing.T) {
	type fields struct {
		key string
	}
	type args struct {
		data interface{}
	}
	tests := []struct {
		name    string
		fields  fields
		args    args
		wantS   string
		wantErr bool
	}{
		{
			name:    "128加密",
			fields:  fields{key: "64ecd6a08ced45ad5d7fedd0c347f6c9"},
			args:    args{data: "{\"phone\": \"00016270252\",\"birth_date\": \"2050-01-01\", \"name\": \"\\u5916\\u90e8\\u51fa\\u884c\\u4eba_\\u6d4b\\u8bd5_1\", \"card_list\": [{\"card_type\": 1, \"card_no\": \"513126199803290017\", \"expire_date\": \"2050-01-01\"}]}"},
			wantS:   "UyCHdn/a5NOCBo9iY+3bTk9hsa4wFK6w1JBjc6L/LKxBuG2/uEgWleRsdtsFT1T6ZkJsbHGC3CBis3IxZN5//SxrZT2VB0gbiewV0cLQH4re6ekMTLWu6AKtJ4IU9ys62QApFypCWVUy2aGlN9WbhvIRD5iJYgXD2J5CIJ5xbpBpzMvLqiBfb3tmicVI3+p8hxXxfSqKr2z99BMzQiFeSsL0TkGniLHUUiuYmfkZVblpnhqYuKidE6Xzeqh6vvMVxlmUjUZ3ZPkrWx+b6ypbTg==",
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			a := &AesTool{
				key: tt.fields.key,
			}
			gotS, err := a.ECBEncrypt128(tt.args.data)
			if (err != nil) != tt.wantErr {
				t.Errorf("ECBEncrypt128() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if gotS != tt.wantS {
				t.Errorf("ECBEncrypt128() gotS = %v, want %v", gotS, tt.wantS)
			}
		})
	}
}

func TestAesTool_ECBDecrypt128(t *testing.T) {
	type fields struct {
		key string
	}
	type args struct {
		src string
	}
	tests := []struct {
		name    string
		fields  fields
		args    args
		wantS   string
		wantErr bool
	}{
		{
			name:    "128解密",
			fields:  fields{key: "64ecd6a08ced45ad5d7fedd0c347f6c9"},
			args:    args{src: "UyCHdn/a5NOCBo9iY+3bTk9hsa4wFK6w1JBjc6L/LKxBuG2/uEgWleRsdtsFT1T6ZkJsbHGC3CBis3IxZN5//SxrZT2VB0gbiewV0cLQH4re6ekMTLWu6AKtJ4IU9ys62QApFypCWVUy2aGlN9WbhvIRD5iJYgXD2J5CIJ5xbpBpzMvLqiBfb3tmicVI3+p8hxXxfSqKr2z99BMzQiFeSsL0TkGniLHUUiuYmfkZVblpnhqYuKidE6Xzeqh6vvMVxlmUjUZ3ZPkrWx+b6ypbTg=="},
			wantS:   "{\"phone\": \"00016270252\",\"birth_date\": \"2050-01-01\", \"name\": \"\\u5916\\u90e8\\u51fa\\u884c\\u4eba_\\u6d4b\\u8bd5_1\", \"card_list\": [{\"card_type\": 1, \"card_no\": \"513126199803290017\", \"expire_date\": \"2050-01-01\"}]}",
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			a := &AesTool{
				key: tt.fields.key,
			}
			gotS, err := a.ECBDecrypt128(tt.args.src)
			if (err != nil) != tt.wantErr {
				t.Errorf("ECBDecrypt128() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if gotS != tt.wantS {
				t.Errorf("ECBDecrypt128() gotS = %v, want %v", gotS, tt.wantS)
			}
		})
	}
}

AES 256

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"errors"
	"reflect"
	"strings"
    "testing"
)

type AesTool struct {
	key string
}

func NewAESTool(k string) *AesTool {
	return &AesTool{
		key: k,
	}
}
func (a *AesTool) ECBEncrypt256(data interface{}) (s string, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = errors.New(e.(string))
		}
	}()
	if data == nil {
		return "", nil
	}
	// 类型转换处理器
	var src []byte
	switch v := data.(type) {
	case []byte:
		src = v 
	case string:
		src = []byte(v) 
	default:
		rv := reflect.Indirect(reflect.ValueOf(v))
		if rv.Kind() == reflect.Struct {
			jsonData, err := json.Marshal(v)
			if err != nil {
				return "", errors.New("json序列化失败")
			}
			src = jsonData
		} else {
			return "", errors.New("不支持的数据类型")
		}
	}
	keyBytes, err := GenerateSecretKeyBytes(2, a.key)
	if err != nil {
		return "", err
	}
	ciphertext := PKCS7Padding([]byte(src), 16)

	//ECB加密
	crypted, err := AesEncrypt(ciphertext, keyBytes)
	if err != nil {
		return "", err
	}
	enc := base64.URLEncoding.WithPadding(base64.StdPadding)
	response := enc.EncodeToString(crypted)
	return response, nil
}

func (a *AesTool) ECBDecrypt256(src string) (s string, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = errors.New(e.(string))
		}
	}()
	replacer := strings.NewReplacer("/", "_", "+", "-")
	src = replacer.Replace(src)
	// 自动补全填充符
	if len(src)%4 != 0 {
		src += strings.Repeat("=", (4-len(src)%4)%4)
	}
	enc, err := base64.URLEncoding.DecodeString(src)
	if err != nil {
		return "", err
	}
	keyBytes, err := GenerateSecretKeyBytes(2, a.key)
	if err != nil {
		return "", err
	}
	// ECB解密
	origin, err := AesDecrypt(enc, []byte(keyBytes))
	if err != nil {
		return "", err
	}

	// 使用PKCS#7对解密后的内容去除填充
	response := string(PKCS7UnPadding(origin))
	return response, nil
}
func (a *AesTool) ECBEncrypt128(data interface{}) (s string, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = errors.New(e.(string))
		}
	}()
	if data == nil {
		return "", nil
	}
	// 类型转换处理器
	var src []byte
	switch v := data.(type) {
	case []byte:
		src = v 
	case string:
		src = []byte(v)
	default:
		rv := reflect.Indirect(reflect.ValueOf(v))
		if rv.Kind() == reflect.Struct {
			jsonData, err := json.Marshal(v)
			if err != nil {
				return "", errors.New("json序列化失败")
			}
			src = jsonData
		} else {
			return "", errors.New("不支持的数据类型")
		}
	}
	keyBytes, err := GenerateSecretKeyBytes(1, a.key)
	if err != nil {
		return "", err
	}

	ciphertext := PKCS7Padding([]byte(src), 16)

	//ECB加密
	crypted, err := AesEncrypt(ciphertext, keyBytes)
	if err != nil {
		return "", err
	}

	response := base64.StdEncoding.EncodeToString(crypted)
	return response, nil
}

func (a *AesTool) ECBDecrypt128(src string) (s string, err error) {
	defer func() {
		if e := recover(); e != nil {
			err = errors.New(e.(string))
		}
	}()
	replacer := strings.NewReplacer("/", "_", "+", "-")
	src = replacer.Replace(src)
	// 自动补全填充符
	if len(src)%4 != 0 {
		src += strings.Repeat("=", (4-len(src)%4)%4)
	}
	enc, err := base64.URLEncoding.DecodeString(src)
	if err != nil {
		return "", err
	}
	keyBytes, err := GenerateSecretKeyBytes(1, a.key)
	if err != nil {
		return "", err
	}
	// ECB解密
	origin, err := AesDecrypt(enc, []byte(keyBytes))
	if err != nil {
		return "", err
	}

	// 使用PKCS#7对解密后的内容去除填充
	response := string(PKCS7UnPadding(origin))
	return response, nil
}

func AesEncrypt(src, key []byte) ([]byte, error) {
	Block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(src) == 0 {
		return nil, errors.New("plaintext empty")
	}
	mode := NewECBEncrypter(Block)
	ciphertext := src
	mode.CryptBlocks(ciphertext, ciphertext)
	return ciphertext, nil
}

// AesDecrypt Aes/ECB模式的解密方法,PKCS7填充方式
func AesDecrypt(src, key []byte) ([]byte, error) {
	Block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(src) == 0 {
		return nil, errors.New("plaintext empty")
	}
	mode := NewECBDecrypter(Block)
	ciphertext := src
	mode.CryptBlocks(ciphertext, ciphertext)
	return ciphertext, nil
}

// ECB模式结构体
type ecb struct {
	b         cipher.Block
	blockSize int
}

// 实例化ECB对象
func newECB(b cipher.Block) *ecb {
	return &ecb{
		b:         b,
		blockSize: b.BlockSize(),
	}
}

// ECB加密类
type ecbEncrypter ecb

func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
	return (*ecbEncrypter)(newECB(b))
}

func (x *ecbEncrypter) BlockSize() int {
	return x.blockSize
}

func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.blockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/cipher: output smaller than input")
	}
	for len(src) > 0 {
		x.b.Encrypt(dst, src[:x.blockSize])
		dst = dst[x.blockSize:]
		src = src[x.blockSize:]
	}
}

// ECB解密类
type ecbDecrypter ecb

func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
	return (*ecbDecrypter)(newECB(b))
}

func (x *ecbDecrypter) BlockSize() int {
	return x.blockSize
}

func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
	if len(src)%x.blockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len(dst) < len(src) {
		panic("crypto/cipher: output smaller than input")
	}
	for len(src) > 0 {
		x.b.Decrypt(dst, src[:x.blockSize])
		dst = dst[x.blockSize:]
		src = src[x.blockSize:]
	}
}

// PKCS7Padding PKCS7填充
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

// PKCS7UnPadding PKCS7去除
func PKCS7UnPadding(ciphertext []byte) []byte {
	length := len(ciphertext)
	unpadding := int(ciphertext[length-1])
	step := length - unpadding
	if step < 0 {
		return []byte{}
	}
	return ciphertext[:step]
}

// GenerateSecretKeyBytes 生成符合AES标准的密钥 ent=0返回空字符串,ent=1使用MD5(128bit),ent=2使用SHA256(256bit)
func GenerateSecretKeyBytes(ent int64, key string) ([]byte, error) {
	switch ent {
	case 0:
		return []byte{}, nil
	case 1:
		return []byte(key), nil
	case 2:
		return HexToBin(key)
	default:
		return nil, errors.New("生成秘钥失败:ent只能是0、1、2")
	}
}

func HexToBin(hexStr string) ([]byte, error) {
	if len(hexStr)%2 != 0 {
		return nil, errors.New("密钥长度必须是128或者256")
	}
	binData, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, errors.New("密钥长度必须是128或者256")
	}
	return binData, nil
}

//AES256单测用例
func TestAesTool_ECBEncrypt256(t *testing.T) {
	type fields struct {
		key string
	}
	type args struct {
		data interface{}
	}
	tests := []struct {
		name    string
		fields  fields
		args    args
		wantS   string
		wantErr bool
	}{
		{
			name:    "256加密",
			fields:  fields{key: "a84c3b673ce6afee65c3c60917c5d0a945504539b8227a827194278b8d1fe77e"},
			args:    args{data: "{\"phone\": \"00016270252\",\"birth_date\": \"2050-01-01\", \"name\": \"\\u5916\\u90e8\\u51fa\\u884c\\u4eba_\\u6d4b\\u8bd5_1\", \"card_list\": [{\"card_type\": 1, \"card_no\": \"513126199803290017\", \"expire_date\": \"2050-01-01\"}]}"},
			wantS:   "ARasLgstrPRPcLXHvI2r1c17OcPui760okbQp5j8ejzOHX4FaBGN-AvsF-x4DUcD9UPS4ovSavh04q2QGYGkeoNyeSkWAzTvfGiX_8t_hLCGOmfaKhnpxhHluLulZE86yDjYt2dYwinmmOO1XNnmajDVGHqIRfYYHK2Grgf6K3wcgGu1wgahhkG0rBPIAI3Y26E3x_INAZZ4EJSxSiH8rx_UzxOz8gLDr53hDyrG1PuUtDdz9bY7lHVGf8oDe_biF1zvqwwOwfZ2uY5bXmxoMA==", // MD5生成16字节密钥‌:ml-citation{ref="1,4" data="citationList"}
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			a := &AesTool{
				key: tt.fields.key,
			}
			gotS, err := a.ECBEncrypt256(tt.args.data)
			if (err != nil) != tt.wantErr {
				t.Errorf("ECBEncrypt256() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if gotS != tt.wantS {
				t.Errorf("ECBEncrypt256() gotS = %v, want %v", gotS, tt.wantS)
			}
		})
	}
}

func TestAesTool_ECBDecrypt256(t *testing.T) {
	type fields struct {
		key string
	}
	type args struct {
		src string
	}
	tests := []struct {
		name    string
		fields  fields
		args    args
		wantS   string
		wantErr bool
	}{
		{
			name:    "256解密",
			fields:  fields{key: "a84c3b673ce6afee65c3c60917c5d0a945504539b8227a827194278b8d1fe77e"},
			args:    args{src: "ARasLgstrPRPcLXHvI2r1c17OcPui760okbQp5j8ejzOHX4FaBGN-AvsF-x4DUcD9UPS4ovSavh04q2QGYGkeoNyeSkWAzTvfGiX_8t_hLCGOmfaKhnpxhHluLulZE86yDjYt2dYwinmmOO1XNnmajDVGHqIRfYYHK2Grgf6K3wcgGu1wgahhkG0rBPIAI3Y26E3x_INAZZ4EJSxSiH8rx_UzxOz8gLDr53hDyrG1PuUtDdz9bY7lHVGf8oDe_biF1zvqwwOwfZ2uY5bXmxoMA=="},
			wantS:   "{\"phone\": \"00016270252\",\"birth_date\": \"2050-01-01\", \"name\": \"\\u5916\\u90e8\\u51fa\\u884c\\u4eba_\\u6d4b\\u8bd5_1\", \"card_list\": [{\"card_type\": 1, \"card_no\": \"513126199803290017\", \"expire_date\": \"2050-01-01\"}]}", // MD5生成16字节密钥‌:ml-citation{ref="1,4" data="citationList"}
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			a := &AesTool{
				key: tt.fields.key,
			}
			gotS, err := a.ECBDecrypt256(tt.args.src)
			if (err != nil) != tt.wantErr {
				t.Errorf("ECBDecrypt256() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if gotS != tt.wantS {
				t.Errorf("ECBDecrypt256() gotS = %v, want %v", gotS, tt.wantS)
			}
		})
	}
}


版本记录

日期

更新内容

上线时间

2025.3.24

增加AES256各版本加密算法

2025.3.24

2025.05.08

java版本加密算法对版本的要求

2025.05.08