字节数组转换为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;
}
验签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);