跳转至

价格加解密示例

Java

java enc/decrypt
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public static String aesEcbPkcs5PaddingEncryptHex(String content, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] rawKey = key.getBytes(StandardCharsets.UTF_8);
    SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

    byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));

    return Hex.encodeHexString(encrypted);
}

public static String aesEcbPkcs5PaddingDecryptHex(String encryptedHex, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] rawKey = key.getBytes(StandardCharsets.UTF_8);
    SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);

    byte[] encrypted = Hex.decodeHex(encryptedHex);
    byte[] decrypted = cipher.doFinal(encrypted);

    return new String(decrypted, StandardCharsets.UTF_8);
}

Golang

实现了自定义的 ECB 加密器和解密器,以模拟 Java 中的 AES/ECB/PKCS5Padding 加密和解密, 此外还添加了用于 PKCS5 填充和去填充的辅助函数

golang enc/decrypt
package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "encoding/hex"
    "fmt"
    "io"
)

func aesEcbPkcs5PaddingEncryptHex(content string, key string) (string, error) {
    rawKey := []byte(key)
    block, err := aes.NewCipher(rawKey)
    if err != nil {
        return "", err
    }

    contentBytes := []byte(content)
    paddedContent := pkcs5Padding(contentBytes, aes.BlockSize)

    encrypted := make([]byte, len(paddedContent))
    ecb := NewECBEncrypter(block)
    ecb.CryptBlocks(encrypted, paddedContent)

    return hex.EncodeToString(encrypted), nil
}

func aesEcbPkcs5PaddingDecryptHex(encryptedHex string, key string) (string, error) {
    rawKey := []byte(key)
    block, err := aes.NewCipher(rawKey)
    if err != nil {
        return "", err
    }

    encrypted, err := hex.DecodeString(encryptedHex)
    if err != nil {
        return "", err
    }

    decrypted := make([]byte, len(encrypted))
    ecb := NewECBDecrypter(block)
    ecb.CryptBlocks(decrypted, encrypted)

    unpaddedContent, err := pkcs5Unpadding(decrypted)
    if err != nil {
        return "", err
    }

    return string(unpaddedContent), nil
}

func pkcs5Padding(data []byte, blockSize int) []byte {
    padding := blockSize - (len(data) % blockSize)
    padText := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(data, padText...)
}

func pkcs5Unpadding(data []byte) ([]byte, error) {
    length := len(data)
    unpadding := int(data[length-1])
    if unpadding > length {
        return nil, errors.New("Invalid padding")
    }
    return data[:(length - unpadding)], nil
}

type ecbEncrypter struct {
    b         cipher.Block
    blockSize int
}

func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
    return &ecbEncrypter{
        b:         b,
        blockSize: b.BlockSize(),
    }
}

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])
        src = src[x.blockSize:]
        dst = dst[x.blockSize:]
    }
}

type ecbDecrypter struct {
    b         cipher.Block
    blockSize int
}

func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
    return &ecbDecrypter{
        b:         b,
        blockSize: b.BlockSize(),
    }
}

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])
        src = src[x.blockSize:]
        dst = dst[x.blockSize:]
    }
}

func main() {
    content := "Hello, World!"
    key := "0123456789abcdef"

    encryptedHex, err := aesEcbPkcs5PaddingEncryptHex(content, key)
    if err != nil {
        fmt.Println("Encryption error:", err)
        return
    }

    fmt.Println("Encrypted Hex:", encryptedHex)

    decrypted, err := aesEcbPkcs5PaddingDecryptHex(encryptedHex, key)
    if err != nil {
        fmt.Println("Decryption error:", err)
        return
    }

    fmt.Println("Decrypted:", decrypted)
}

PHP

php enc/decrypt
<?php
function aesEcbPkcs5PaddingEncryptHex($content, $key) {
    $rawKey = mb_convert_encoding($key, 'UTF-8');
    $skeySpec = new \stdClass();
    $skeySpec->key = $rawKey;
    $skeySpec->algorithm = 'AES';

    $cipher = openssl_encrypt($content, 'AES-128-ECB', $skeySpec->key, OPENSSL_RAW_DATA);
    $encrypted = bin2hex($cipher);

    return $encrypted;
}

function aesEcbPkcs5PaddingDecryptHex($encryptedHex, $key) {
    $rawKey = mb_convert_encoding($key, 'UTF-8');
    $skeySpec = new \stdClass();
    $skeySpec->key = $rawKey;
    $skeySpec->algorithm = 'AES';

    $encrypted = hex2bin($encryptedHex);
    $decrypted = openssl_decrypt($encrypted, 'AES-128-ECB', $skeySpec->key, OPENSSL_RAW_DATA);

    return $decrypted;
}

$content = "Hello, World!";
$key = "0123456789abcdef";

$encryptedHex = aesEcbPkcs5PaddingEncryptHex($content, $key);
echo "Encrypted Hex: " . $encryptedHex . "\n";

$decrypted = aesEcbPkcs5PaddingDecryptHex($encryptedHex, $key);
echo "Decrypted: " . $decrypted . "\n";