哎 感谢提前阅读。
我在加密3des中的某些问题时遇到了一些问题,它正在运行,但似乎没有出现正确的值
目的: 我需要从PHP验证其他API,以便能够检索信息, 他们的文件说明了这一点:
我已经实现了以下代码,但不确定是否做错了, 这里有来自文档的一些信息
生成密钥的过程如下:
1.华为定义的内部值99991231加入明文加密。结果A生成
2.在结果A上执行标准MD5算法。生成结果B.
3.结果B转换为十六进制数。结果C生成
如果十六进制字符串中的第一个字符为0,则忽略它。如果另一个字符为0,则保留它。例如,0x0100101F3B转换为100101F3B
4.获得结果C中的前八个字符。结果D生成
5.结果D中的字符将转换为小写字符。生成加密文本。
这是他们提供的用于生成md5 huawei的示例代码(我认为它的java?需要它的PHP等价物)
byte[] id = plainPwd.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(id);
md.update("99991231".getBytes()); // “99991231” mentioned in XML-API DOC
byte[] buffer = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i <buffer.length; i++) {
sb.append(Integer.toHexString((int) buffer[i] & 0xff));
}
String md5Pwd = sb.substring(0, 8); // only use first 8 characters
这就是所需要的:
3DES加密算法用于生成验证器。要加密的纯文本格式如下: 随机+&#34; $&#34 + EncryToken +&#34; $&#34 +的userid +&#34; $&#34 + terminalid +&#34; $&#34 + terminalip + &#34; $&#34 + MAC +&#34; $&#34 +保留+&#34; $&#34; +&#34; CTC&#34;
他们的密钥基于此生成:
3DES加密结果转换为
的十六进制字符串 ASCII模式,其中字母A到F是大写的。例如,如果是 3DES加密结果为0x0123456789ABCDEF,值为
Authenticator是0123456789ABCDEF。生成的过程 验证者如下:
1.客户端向EPG服务器发送订户认证请求。请求URL:http ... / XML / Authenticate
UserID:10086Mac地址:ABCDEFGH
2. EPG服务器返回enctytoken(例如,AD75B1697FB5EB6345B2D412124030D2)和encryptiontype(例如, MD5)给客户。
3.客户端使用MD5算法加密用户的密码(例如,纯文本中的0)以生成密钥,例如, db90e7eb。
4.客户端随机生成一个字符串,例如20926330 5.客户端根据每个参数生成要加密的纯文本字符串。以下是一个例子:
20926330 $ AD75B1697FB5EB6345B2D412124030D2 $ 10086 $ 10086 $ 10.164.111 $ ABCDEFGH $保留$ CTC
6.客户端使用3DES算法加密字符串以生成验证器。以下是代码示例:
567A7A72AE33C8867936AB0190EC9F2405B20D4A4808D2A8E8CBC0D7D5482E4F53454EA4F37A29B81A63ECB0BF717E96505EE59476799D932F16AEBFECE097171159095DC57DA84D91930AF92EF96E75486DEA0DEA781D51
他们也有这个代码(我认为java)的例子,我也需要它在PHP中的等价物:
public class DESUtil
{
private static final String Algorithm = "DESede/ECB/PKCS5Padding";// DESede/ECB/PKCS5Padding;DESede
private static final String DESede = "DESede";
public static byte[] encrypt(byte[] keybyte, byte[] src)
throws NoSuchAlgorithmException, NoSuchPaddingException, Exception
{
SecretKey deskey = new SecretKeySpec(keybyte, DESede);
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.ENCRYPT_MODE, deskey);
return c1.doFinal(src);
}
public static byte[] decrypt(byte[] keybyte, byte[] src)
throws NoSuchAlgorithmException, NoSuchPaddingException, Exception
{
SecretKey deskey = new SecretKeySpec(keybyte, DESede);
Cipher c1 = Cipher.getInstance(Algorithm);
c1.init(Cipher.DECRYPT_MODE, deskey);
return c1.doFinal(src);
}
public static String byte2hex(byte[] b)
{
StringBuffer hs = new StringBuffer();
String stmp = "";
for (int n = 0; n <b.length; n++)
{
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1)
hs.append("0").append(stmp);
else
hs.append(stmp);
}
return hs.toString().toUpperCase(Locale.getDefault());
}
public static byte[] hex2byte(String hexStr)
{
if (hexStr.length() % 2 != 0)
{
AppLogger.error("hex2bytes's hexStr length is not even.");
return null;
}
byte[] toBytes = new byte[hexStr.length() / 2];
for (int i = 0, j = 0; i <hexStr.length(); j++, i = i + 2)
{
int tmpa = Integer.decode(
"0X" + hexStr.charAt(i) + hexStr.charAt(i + 1)).intValue();
toBytes[j] = (byte) (tmpa & 0XFF);
}
return toBytes;
}
public static void main(String[] args)
{
Security.addProvider(new com.sun.crypto.provider.SunJCE());
final byte[] rawKey = "db90e7eb".getBytes();
final byte[] keyBytes = new byte[24];
for (int i = 0; i <rawKey.length; i++)
{
keyBytes[i] = rawKey[i];
}
for (int i = rawKey.length; i <keyBytes.length; i++)
{
keyBytes[i] = (byte)0;
}
String szSrc = "20926330$AD75B1697FB5EB6345B2D412124030D2$10086$10086$10.164.111$ABCDEFGH$Reserved$CTC";
System.out.println("string before encrypt:" + szSrc);
byte[] encoded = null;
try
{
encoded = encrypt(keyBytes, szSrc.getBytes());
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("string after encrypt::" + byte2hex(encoded));
byte[] srcBytes = null;
try
{
srcBytes = decrypt(keyBytes, encoded);
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("string before decode: :" + (new String(srcBytes)));
}
}
我基于一些在线参考文件做的PHP代码如下,但api似乎不喜欢它,加密代码长度似乎太长,这是我的代码+ api的响应的结果:
加密: y8V17%2BEImP88UyoQRfGbjldYjfGzsR4r%2B04sE1kPOwPdQNeH1jEhZMYTAgdgeinT6A%2BUfXCFI5KN9QDCTq2oz7AZqTlFEfztQRdgW2ij6YvwQVbRsblJwA%3D%3D
解密 15173232 $ $ BCE723AE4BC97FAD6293D73B2266361D $ 20140409 20140409 $$ ABCDEFGH $保留$ CTC
加密的十六进制: 793856313725324245496D50383855796F51526647626A6C64596A66477A7352347225324230347345316B504F775064514E6548316A45685A4D59544167646765696E543641253242556658434649354B4E395144435471326F7A37415A71546C4645667A74515264675732696A365976775156625273626C4A7741253344253344
3des身份验证员: y8V17%2BEImP88UyoQRfGbjldYjfGzsR4r%2B04sE1kPOwPdQNeH1jEhZMYTAgdgeinT6A%2BUfXCFI5KN9QDCTq2oz7AZqTlFEfztQRdgW2ij6YvwQVbRsblJwA%3D%3D
SimpleXMLElement对象(
[retmsg] => 3DES decrypt error second time(0x30), please check epg's encrytMode and acs's encryMode.
要检查我的PHP代码是否有任何错误的细节:
$userid = '123';
$terminalip = '';
$mac = 'ABCDEFGH';
$terminalid = $userid;
$pin = '123';
$encToken = 'testtest';
$encryption_key = $pin;
$authenticator = rand(0,99999999).'$'.$encToken.'$'.$userid.'$'.$terminalid.'$'.$terminalip.'$'.$mac.'$'.'Reserved'.'$'.'CTC';
$desEncryptedData = encrypt($authenticator, $encryption_key);
echo "encrypted: <br>".$desEncryptedData;
echo"<br><br><br><b>Decrypt</b><br>";
$d = decrypt($desEncryptedData,$encryption_key);
echo $d;
echo "<BR><BR>encrypted hex: <br>". strToHex($desEncryptedData);
echo "<br><br>3des authenticator: <br>".$desEncryptedData."<br />";
$req = "<?xml version='1.0' encoding='UTF-8'?>
<AuthenticateReq>
<userid>$userid</userid>
<authenticator>$desEncryptedData</authenticator>
</AuthenticateReq>
";
// the functions to use to login
$context = stream_context_create(array('http'=>array(
'method' => 'POST',
'header' => "Content-Type: text/xml\r\n",
'content' => $req
)));
function encrypt($input,$ky)
{
$key = $ky;
$size = mcrypt_get_block_size(MCRYPT_TRIPLEDES, 'ecb');
$input = pkcs5_pad($input, $size);
$td = mcrypt_module_open(MCRYPT_TRIPLEDES, '', '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);
$data = urlencode($data); //push it out so i can check it works
return $data;
}
function decrypt($crypt,$ky)
{
$crypt = urldecode($crypt);
$crypt = base64_decode($crypt);
$key = $ky;
$td = mcrypt_module_open (MCRYPT_TRIPLEDES, '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$decrypted_data = mdecrypt_generic ($td, $crypt);
mcrypt_generic_deinit ($td);
mcrypt_module_close ($td);
$decrypted_data = pkcs5_unpad($decrypted_data);
$decrypted_data = rtrim($decrypted_data);
return $decrypted_data;
}
function pkcs5_pad($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function pkcs5_unpad($text)
{
$pad = ord($text{strlen($text)-1});
if ($pad > strlen($text)) return false;
return substr($text, 0, -1 * $pad);
}
function strToHex($string){
$hex = '';
for ($i=0; $i<strlen($string); $i++){
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0'.$hexCode, -2);
}
return strToUpper($hex);
}
非常感谢您的提前时间