代码示例
字节数组转换为16进制字符串示例
代码参考(C#):
public static string HexString(byte[] baSrc) { if (baSrc == null) { return ""; } int nByteNum = baSrc.Length; StringBuilder sbResult = new StringBuilder(nByteNum * 2); for (int i = 0; i < nByteNum; i++) { char chHex; byte btHigh = (byte)((baSrc[i] & 0xF0) >> 4); if (btHigh < 10) { chHex = (char)('0' + btHigh); } else { chHex = (char)('A' + (btHigh - 10)); } sbResult.Append(chHex); byte btLow = (byte)(baSrc[i] & 0x0F); if (btLow < 10) { chHex = (char)('0' + btLow); } else { chHex = (char)('A' + (btLow - 10)); } sbResult.Append(chHex); } return sbResult.ToString(); }
商户支付密钥签名示例
代码参考(C#):
// 假设已排序的待签名字符串为:strToSign //拼接支付密钥 strToSign+= "&" + sMerchantKey; //SHA-256签名 byte[] baSrc = Encoding.GetEncoding(“UTF-8”).GetBytes(strToSign.ToString()); SHA256 sha = new SHA256CryptoServiceProvider(); byte[] baResult = sha.ComputeHash(baSrc); //转为16进制字符串 string sign = HexString(baResult);
代码参考java版:
//假设已排序字符串为strToSign //添加商户密钥 strToSign.append(“&”).append(sMerchantKey); // 创建加密对象 MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); // 传入要加密的字符串,按指定的字符集将字符串转换为字节流 messageDigest.update(strToSign.toString().getBytes("UTF-8")); byte byteBuffer[] = messageDigest.digest(); // 將 byte数组转换为16进制string String sign = HexString.toString();
代码参考php版:
// 假设已排序的待签名字符串为strToSign //拼接支付密钥 $strToSign .= '&'.$sMerchantKey; //SHA-256签名 $baSrc = mb_convert_encoding($strToSign,"UTF-8"); $baResult = hash('sha256', $baSrc); //转为16进制字符串(可选) $sign = bin2hex($baResult);
招行公钥验签示例
验签java示例:
public static boolean isValidSignature(String strToSign, String strSign, String publicKey) { try { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] encodedKey = Base64.decode(publicKey); PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); java.security.Signature signature = java.security.Signature .getInstance("SHA1WithRSA"); signature.initVerify(pubKey); signature.update(strToSign.getBytes(“UTF-8”) ); boolean bverify = signature.verify( Base64.decode(strSign) ); return bverify; } catch (Exception e) { e.printStackTrace(); } return false; }
待签名字符串strToSign 排序java示例:
JSONObject joNoticeData = joMain.getJSONObject("noticeData"); //按字典顺序排序,即字母顺序与大小写无关 List<String> keys = new ArrayList<String>(joNoticeData.keySet()); Collections.sort(keys, new Comparator<String>() { public int compare(String s1, String s2) { int i = s1.toLowerCase().compareTo(s2.toLowerCase()); if (i != 0) { return i; } return s2.compareTo(s1); } }); StringBuilder sb = new StringBuilder(); for (String key : keys) { sb.append("&").append(key).append("=").append(joNoticeData.getString(key)); }
验签php示例:
//公钥 $pub_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZs4l8Ez3F4MG0kF7RRSL+pn8MmxVE3nfdXzjx6d3rH8IfDbNvNRLS0X0b5iJnPyFO8sbbUo1Im4zX0M8XA0xnnviGyn5E6occiyUXJRgokphWb5BwaYdVhnLldctdimHoJTk3NFEQFav3guygR54i3tymrDc8lWtuG8EczVu8FwIDAQAB'; //待验证签名字符串 $toSign_str = 'branchNo=0101&dateTime=20160701123456&httpMethod=POST&merchantNo=123456¬iceSerialNo=201607019876543210¬iceType=ABCDEFGH¬iceUrl=http://99.12.38.88:8086/RecvNotice/NoticeRcv.ashx¶m1=111¶m2=a中转周末b'; //签名结果(strSign) $sig_dat = 'Pez08MLS6tnrPTnO2febDbHmZ1FNB8Rgy1dp82XwPXkWbP0XPFZAy0ElRomJnMGuGNEwz9hC61TUNhRYhb22ZEHhFMpMNZWFeiN1ewXwIT5Sx7VmE4InfklQnVub0dRr1d6zJ3gprMHBoiQBe8xAxpd1y+82Jm5z7IkvLtgWXU4='; //处理证书 $pem = chunk_split($pub_key, 64, "\n"); $pem = "-----BEGIN PUBLIC KEY-----\n" . $pem . "-----END PUBLIC KEY-----\n"; $pkid = openssl_pkey_get_public($pem); if (empty($pkid)) { die('获取 pkey 失败'); } //验证 $ok = openssl_verify($toSign_str, base64_decode($sig_dat), $pkid, OPENSSL_ALGO_SHA1); var_dump($ok); die();
验签C#示例(双击图标打开文件):
DES加密示例
注意:使用DES算法加密,加密需要取商户支付密钥的前8位,不足8位则右补0。
代码参考(C#):
public static byte[] DESEncrypt(byte[] plain, byte[] key) { DESCryptoServiceProvider des = new DESCryptoServiceProvider(); des.Mode = CipherMode.ECB; des.Padding = PaddingMode.PKCS7; return des.CreateEncryptor(key, key).TransformFinalBlock(plain, 0, plain.Length); } public static byte[] DESDecrypt(byte[] encrypt, byte[] key) { DESCryptoServiceProvider des = new DESCryptoServiceProvider(); des.Mode = CipherMode.ECB; des.Padding = PaddingMode.PKCS7; return des.CreateDecryptor(key, key).TransformFinalBlock(encrypt, 0, encrypt.Length); } //调用 byte[] byteKey = Encoding.UTF8.GetBytes(sKey); byte[] baCiphertext =DESEncrypt(Encoding.UTF8.GetBytes(sBodyContent), byteKey); string sCiphertext = HexString(baCiphertext);
代码参考(JAVA):
public static byte[] DesEncrypt(byte[] plain, byte[] key) { try{ SecureRandom random = new SecureRandom(); DESKeySpec desKeySpec = new DESKeySpec(key); //创建一个密匙工厂,然后用它把DESKeySpec转换成 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey securekey = keyFactory.generateSecret(desKeySpec); //Cipher对象实际完成加密操作 Cipher cipher = Cipher.getInstance("DES");//DES/ECB/PKCS5Padding //用密匙初始化Cipher对象 cipher.init(Cipher.ENCRYPT_MODE, securekey, random); //现在,获取数据并加密 //正式执行加密操作 return cipher.doFinal(plain); } catch(Throwable e) { e.printStackTrace(); } return null; } //调用 try { byte[] byteKey = desKey.getBytes("UTF-8"); byte[] byteBodyContent = sBodyContent.getBytes("UTF-8"); byte[] baCiphertext = TestDes.DesEncrypt(byteBodyContent, byteKey); //将byte转为16进制字符串 } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); }
RC4加密示例
算法代码参考(C#):
/// <summary> /// RC4加密。 /// RC4为对称加密算法,两次加密即为解密。明文/密文数据长度相同 /// <summary> /// <param name="baSrc">明文数据</param> /// <param name="nSrcLen">明文数据长度</param> /// <param name="baKey">密钥</param> /// <param name="nKeyLen">密钥长度</param> /// <param name="baDst">密文数据</param> /// <param name="nDstLen">密文数据长度</param> /// <returns>加密数据长度。即明/密文数据长度</returns> public static int RC4Encrypt(byte[] baSrc, int nSrcLen, byte[] baKey, int nKeyLen, byte[] baDst, int nDstLen) { byte[] S = new byte[256]; //状态向量S byte[] T = new byte[256]; //临时向量T int i, j; //状态向量S的初始化 for (i = 0; i < 256; i++) { S[i] = (byte)i; T[i] = baKey[i % nKeyLen]; } j = 0; byte temp; for (i = 0; i < 256; i++) { j = (j + (int)S[i] + T[i]) % 256; temp = S[i]; S[i] = S[j]; S[j] = temp; } //状态向量S的初始化结束 i = 0; j = 0; int t; char k; int n = 0; while (nSrcLen != 0) { i = (i + 1) % 256; j = (j + S[i]) % 256; temp = S[i]; S[i] = S[j]; S[j] = temp; t = (S[i] + S[j]) % 256; k = (char)S[t]; baDst[n] = (byte)(baSrc[n] ^ k); n++; nSrcLen--; } return n; }
调用:
byte[] baSrc = Encoding.UTF8.GetBytes(sSrc); byte[] baKey = Encoding.UTF8.GetBytes(sKey); byte[] baCiphertext = new byte[baSrc.Length]; RC4Encrypt(baSrc, baSrc.Length, baKey, baKey.Length, baCiphertext, baCiphertext.Length); string sCiphertext = HexString(baCiphertext);