💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、豆包、星火、月之暗面及文生图、文生视频 广告
# 验签解密代码示例 * java示例 [Base64包下载](https://file.10ss.net/live_sys_pkg/Base64.java) ``` import org.junit.Test; import javax.crypto.Cipher; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.PublicKey; import java.security.Signature; import java.security.spec.X509EncodedKeySpec; public class verifySignAndDecrypteDemo { /** * 应用设置 -> K8推送 -> 设置 -> 接口加签名方式(密钥) -> 平台公钥 */ public static final String publicKey = ""; /** * 第一步:验签操作 */ @Test public void verifySign() { // 交易报文中ciphertext与signature String ciphertext = ""; String signature = ""; byte[] signatureByte = Base64.decodeBase64String(signature); byte[] publicKeyByte = Base64.decodeBase64String(publicKey); try { System.out.println("验签结果:" + verify(ciphertext.getBytes(), signatureByte, publicKeyByte)); } catch (GeneralSecurityException e) { e.printStackTrace(); } } /** * 第二步:解析参数 */ @Test public void decrypte() throws Exception { // 交易报文中ciphertext与tag和iv String ciphertext = ""; String tag = ""; String iv = ""; // 应用设置 -> K8推送 -> 设置 -> 接口加签名方式(密钥) -> 应用公钥 String key = ""; try { String plaintext = decrypte(Base64.decodeBase64String(ciphertext), key.getBytes(), iv.getBytes(), Base64.decodeBase64String(tag)); System.out.println(plaintext); } catch (Exception e) { throw new Exception(e); } } private static boolean verify(byte[] data, byte[] signature, byte[] publicKey) throws GeneralSecurityException { X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey pubKey = keyFactory.generatePublic(pubKeySpec); Signature sig = Signature.getInstance("SHA256withRSA"); sig.initVerify(pubKey); sig.update(data); return sig.verify(signature); } /** * AES-GCM-256对称解密 */ private static String decrypte(byte[] encryptedBytes, byte[] keyBytes, byte[] ivBytes, byte[] tagBytes) throws Exception { SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, ivBytes); cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmParameterSpec); cipher.updateAAD("transaction".getBytes(StandardCharsets.UTF_8)); cipher.update(encryptedBytes); byte[] decryptedBytes = cipher.doFinal(tagBytes); String decryptedString = new String(decryptedBytes, StandardCharsets.UTF_8); byte[] content = Base64.decodeBase64String(decryptedString); return new String(content); } } ``` * golang示例 ``` package main import ( "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) type Args struct { Ciphertext string `json:"ciphertext"` Nonce string `json:"nonce"` Tag string `json:"tag"` Key string `json:"key"` } func decryptAES256GCM(args Args) (string, error) { var extra []byte extra = []byte(args.AdditionalData) key := []byte(args.Key) nonce, _ := base64.StdEncoding.DecodeString(args.Nonce) tag, _ := base64.StdEncoding.DecodeString(args.Tag) ciphertext, _ := base64.StdEncoding.DecodeString(args.Ciphertext) x := append(ciphertext, tag...) block, err := aes.NewCipher(key) if err != nil { return "", fmt.Errorf("failed to create cipher: %v", err) } aesgcm, err := cipher.NewGCMWithNonceSize(block, aes.BlockSize) if err != nil { return "", fmt.Errorf("failed to create GCM: %v", err) } plaintext, err := aesgcm.Open(nil, nonce, x, extra) if err != nil { return "", fmt.Errorf("failed to decrypt: %v", err) } return string(plaintext), nil } func main() { args := Args{ Ciphertext: "这里是平台POST过来的加密密文,参数名ciphertext,还没Base64解码的", Nonce: "这里是平台POST过来的,参数名nonce", Tag: "这里是平台POST过来的,参数名tag,还没Base64解码的", AdditionalData: "transaction", Key: "这里是后台设置的密钥,32位字符", } plaintext, err := decryptAES256GCM(args) if err != nil { fmt.Printf("Failed to decrypt: %v\n", err) } else { fmt.Println(plaintext) } } ``` * php示例 ``` <?php namespace app\controller; use app\BaseController; use think\facade\Log; class Index extends BaseController { // 开放平台平台公钥 protected static $rsa_public_key = ''; // 开放平台应用公匙 protected static $aes_encryption_key = ''; public function index() { $message = ''; $postData = $_POST; if ($postData) { $content = json_encode($postData); Log::info("[推送参数]----[postData][$content]"); $isVerify = self::verifySignature($postData['ciphertext'], self::$rsa_public_key, base64_decode($postData['signature'])); if (!$isVerify) { $message = '验签失败'; } $params = self::decode(base64_decode($postData['ciphertext']), self::$aes_encryption_key, $postData['iv'], base64_decode($postData['tag'])); $paramsContent = json_encode($params); if (!$params) { $message = '解密失败'; } Log::info("[推送解密后参数]----[postData][$paramsContent]"); ## todo 后续对接自己项目功能 ## todo 对接打印机小票打印 } return json($this->result($message)); } /** * Notes: 验证签名 * @param $data * @param $privateKey */ public static function verifySignature($data, $publicKey, $signature) { return openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256); } /** * Notes: 解密 * @param $string * @param $key * @param $iv * @param $tag * @param $additionalData * @return false|string */ public static function decode($string, $key, $iv, $tag, $additionalData = 'transaction') { $decrypted = openssl_decrypt($string, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag, $additionalData); $decrypted = base64_decode($decrypted); return $decrypted; } /** * Notes: 返回处理 * @param string $message * @return array */ protected function result($message = '') { return [ 'message' => 'ok', 'dataMsg' => $message, ]; } } ``` * C#示例 ``` public class AESGCM { public static string Decrypt() { // AES-256-GCM 使用 BouncyCastle.Crypto 库,从NuGet下载 // 平台POST过来的是Form参数,从Request.Form中提取 var arg = new { ciphertext = "这里是平台POST过来的加密密文,参数名ciphertext,还没Base64解码的", iv = "", // 同 nonce,重复的 nonce = "这里是平台POST过来的,参数名nonce", // 解密用的向量 tag = "这里是平台POST过来的,参数名tag,还没Base64解码的", additional_data = "transaction", key = "这里是后台设置的密钥,32位字符" }; var extra = Encoding.UTF8.GetBytes(arg.additional_data); var key = Encoding.UTF8.GetBytes(arg.key); var nonce = Encoding.UTF8.GetBytes(arg.nonce); var tag = Convert.FromBase64String(arg.tag); var x = Convert.FromBase64String(arg.ciphertext); x = x.Concat(tag).ToArray(); try { var cipher = new GcmBlockCipher(new AesFastEngine()); var aead = new AeadParameters(new KeyParameter(key), 128, nonce, extra); cipher.Init(false, aead); var data = new byte[cipher.GetOutputSize(x.Length)]; var num = cipher.ProcessBytes(x, 0, x.Length, data, 0); cipher.DoFinal(data, num); var a = Encoding.UTF8.GetString(data); // 解密成功得到 base64 string var b = Convert.FromBase64String(a); // base64 转为 byte[] var c = Encoding.UTF8.GetString(b); // 转为最终的JSON明文,成功了 return c; } catch (Exception ex) { Console.WriteLine(ex); // 这里异常说明key 不对,key需要纯32位字符,建议key生成这样的 Guid.NewGuid().ToString("n") } return null; } } ``` * nodejs示例 ``` //验证签名 let verify = crypto.createVerify('SHA256'); verify.update(jo_body.ciphertext); let verify_result = verify.verify(平台公钥, jo_body.signature, 'base64'); if (!verify_result) throw new Error('签名验证失败'); //数据解密 let ciphertext = Buffer.from(jo_body.ciphertext, 'base64'); let tag = Buffer.from(jo_body.tag, 'base64'); let decipher = crypto.createDecipheriv('aes-256-gcm', 应用公钥, jo_body.iv); decipher.setAuthTag(tag); decipher.setAAD(Buffer.from('transaction')); let decoded = decipher.update(ciphertext, null, 'utf8'); decipher.final(); let payData = JSON.parse(Buffer.from(decoded, 'base64').toString()); //解密后的数据 console.log('解密后的数据', payData); ```