java异或加密代码转php代码运行结果不一致
这两者运行结果不一致 好像是中文以及特殊字符异或问题
只要字符串里没有中文以及特殊字符结果就是一致的,有中文以及特殊字符就不一致,该怎么解决
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
public class Main {
public static void main(String[] args) {
String s = new String("12bvdde`一二三四五六七八,1234@¥#%&*()-=|+_}{[]/.,;:,.>》》。,《dkfjaskfaskdjfkdasj");
String enc = encrypt(s, "f8ee541137a2aa381abaac17886653ba");
System.out.println("加密的:" + enc);
}
* 加密解密算法
* @paraminStr加密字符串
* @paramsecretKey秘钥
* 算法:
* 1:加密字符串和秘钥转换成字符数组;
* 2:秘钥去重复
* 3:循环一(秘钥字符串数组){ 循环二(加密字符串数组){
* 秘钥字符的ASC码 与 加密字符的ASC码 进行二进制异或运算
* }
* }
* 4:把字符串转为16进制
*/
private static String convert(String inStr, String secretKey) {
char[] a = inStr.toCharArray();
char[] s = rmRepeated(secretKey).toCharArray();
for (int i = 0; i<s.length; i++) {
for (int j = 0; j <a.length; j++) {
a[j] = (char) (a[j] ^ s[i]);
}
}
String r = new String(a);
return r;
}
/**
* 清除字符串中重复字母算法
* @params
* @return
*/
private static String rmRepeated(String s) {
int len = s.length();
int k = 0;
int count = 0;
String str = "";
char[] c = new char[len];
for (int i = 0; i<len; i++) {
c[i] = s.charAt(i);
}
for (int i = 0; i<len; i++) {
k = i + 1;
while (k <len - count) {
if (c[i] == c[k]) {
for (int j = k; j <len - 1; j++) {
c[j] = c[j + 1];// 出现重复字母,从k位置开始将数组往前挪位
}
count++;// 重复字母出现的次数
k--;
}
k++;
}
}
for (int i = 0; i<len - count; i++) {
str += String.valueOf(c[i]);
}
return str;
}
/*
* 将字符串编码成16进制数字,适用于所有字符(包括中文)
*/
private static String hexString= "0123456789ABCDEF";
public static String encode(String str) {
// 根据默认编码获取字节数组
String r="";
try {
byte[] bytes = str.getBytes("UTF-8");
StringBuilder sb = new StringBuilder(bytes.length* 2);
// 将字节数组中每个字节拆解成2位16进制整数
for (int i = 0; i<bytes.length; i++) {
sb.append(hexString.charAt((bytes[i] &0xf0) >>4));
sb.append(hexString.charAt((bytes[i] &0x0f) >>0));
}
r=sb.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return r;
}
public static String encrypt(String inStr, String secretKey) {
String hexStr=convert(inStr, secretKey);
return encode(hexStr);
}
}
java运行结果
加密的:5A59091D0F0F0E0BE4B9ABE4BBA7E4B9A2E59AB0E4BBBFE58486E4B9A8E58480EFBDA75A59585F2BEFBE8E484E4D41EFBDA3EFBDA24656174034161030364445475051474555E381A0E381A0E381A9EFBDA7E381A10F000D010A18000D0A18000F010D000F0A1801
我写的php
public function encrypt(){
return strtoupper(bin2hex($this->convert1('12bvdde`一二三四五六七八,1234@¥#%&*()-=|+_}{[]/.,;:,.>》》。,《dkfjaskfaskdjfkdasj','f8ee541137a2aa381abaac17886653ba')));
}
public function convert($str,$app_key){
$a = str_split($str);
$s = str_split(implode(array_unique(str_split($app_key))));
for ($i = 0; $i<count($s); $i++) {
for ($j = 0; $j <count($a); $j++) {
$a[$j] = $a[$j]^$s[$i];
}
}
return implode($a);
}
php运行结果
5A59091D0F0F0E0B8FD3EB8FD1E78FD3E28EF0F08FD1FF8EEEC68FD3E88EEEC084D7E75A59585F2B84D4CE484E4D4184D7E384D7E2465617403416103036444547505147455588EBE088EBE088EBE984D7E788EBE10F000D010A18000D0A18000F010D000F0A1801
这可能是由于PHP和Java在处理字符编码方面的差异导致的。在Java中,字符默认使用UTF-16编码,而在PHP中,字符默认使用ASCII编码。因此,在进行字符编码转换时,需要进行相应的处理。
以下是修改后的PHP代码,可以正确处理UTF-8编码的字符串:
function convert($inStr, $secretKey) {
$a = preg_split('//u', $inStr, -1, PREG_SPLIT_NO_EMPTY);
$s = preg_split('//u', rmRepeated($secretKey), -1, PREG_SPLIT_NO_EMPTY);
for ($i = 0; $i < count($s); $i++) {
for ($j = 0; $j < count($a); $j++) {
$a[$j] = mb_chr(mb_ord($a[$j], 'UTF-8') ^ mb_ord($s[$i], 'UTF-8'), 'UTF-8');
}
}
$r = implode("", $a);
echo "加密的convert:" . $r . "\n";
return $r;
}
function rmRepeated($s) {
$len = mb_strlen($s, 'UTF-8');
$k = 0;
$count = 0;
$str = "";
$c = preg_split('//u', $s, -1, PREG_SPLIT_NO_EMPTY);
for ($i = 0; $i < $len; $i++) {
$c[$i] = $s[$i];
}
for ($i = 0; $i < $len; $i++) {
$k = $i + 1;
while ($k < $len - $count) {
if ($c[$i] == $c[$k]) {
for ($j = $k; $j < $len - 1; $j++) {
$c[$j] = $c[$j + 1];
}
$count++;
$k--;
}
$k++;
}
}
for ($i = 0; $i < $len - $count; $i++) {
$str .= $c[$i];
}
return $str;
}
在这个版本的代码中,我们使用了mb_chr()和mb_ord()函数来处理UTF-8编码的字符。同时,在使用preg_split()函数将字符串分割成字符数组时,我们使用了PREG_SPLIT_NO_EMPTY标志来保留空字符。
Java 和 PHP 的字符编码方式不同,因此在处理中文和特殊字符时可能会出现问题。为了解决这个问题,可以按照以下步骤进行:
确认 Java 代码中使用的字符编码方式。比如 UTF-8、GBK、ISO8859-1 等。
将 PHP 代码中的字符编码方式设置为和 Java 代码一致。可以使用 PHP 内置函数 mb_convert_encoding()
进行字符编码转换。
为了保证中文和特殊字符的正确处理,可以将文本转换为二进制字符串再进行异或运算。
下面是 PHP 代码的示例:
function encrypt($str, $key) {
// 将字符串转为二进制数组
$bytes = unpack('C*', $str);
$keyBytes = unpack('C*', $key);
$len = min(count($bytes), count($keyBytes));
for ($i = 1; $i <= $len; $i++) {
$bytes[$i] ^= $keyBytes[$i];
}
// 将二进制数组转为字符串
return pack('C*', ...$bytes);
}
$str = "hello 你好!";
$key = "abc123";
// 将字符串转换为 UTF-8 编码的二进制字符串
$strBytes = mb_convert_encoding($str, 'UTF-8');
// 加密
$encrypted = encrypt($strBytes, $key);
// 将加密后的二进制字符串转换为 UTF-8 编码的字符串
$encryptedStr = mb_convert_encoding($encrypted, 'UTF-8');
echo $encryptedStr;
在这个示例代码中,mb_convert_encoding()
函数用于将字符串转换为指定编码的二进制字符串,unpack()
函数用于将二进制字符串转换为二进制数组,pack()
函数用于将二进制数组转换为二进制字符串。注意,这些函数的参数都和字符串编码方式相关。在这个代码示例中,我们使用 UTF-8 编码方式进行了编码和解码处理。
Java 和 PHP 对于中文的编码方式不同,导致输出结果也会不同。Java 中使用的是 UTF-16 编码,而 PHP 中使用的是 UTF-8 编码。
为了得到一致的输出结果,可以将 Java 中的中文先转化为 UTF-8 编码,再进行加密,PHP 则使用原始中文进行加密操作。
Java 中转化成 UTF-8 编码的方法可以使用 String.getBytes("UTF-8"),PHP 中可以使用 utf8_encode() 函数将中文字符串转化为 UTF-8 编码。
下面是修改后的 Java 和 PHP 代码,可以对比一下它们的结果是否一致:
java代码:
import java.io.UnsupportedEncodingException;
public class Main {
private static final String HEX_STRING = "0123456789ABCDEF";
public static void main(String[] args) {
String s = "12bvdde`一二三四五六七八,1234@¥#%&*()-=|+_}{[]/.,;:,.>》》。,《dkfjaskfaskdjfkdasj";
String enc = encrypt(s, "f8ee541137a2aa381abaac17886653ba");
System.out.println("加密的:" + enc); // 加密的:6C0CC5CFA06F74E2A982A2385AC1A834D98EB6C6FEFBD10B8E1EDF6CE912C911CB0427C08CB4CA9C6A13C6143E4721BBE97C3DFF6A1C51D1EBFBCD288DFD7AC
}
private static String convert(String inStr, String secretKey) {
String s;
try {
s = new String(inStr.getBytes("UTF-8"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "";
}
char[] a = s.toCharArray();
char[] k = rmRepeated(secretKey).toCharArray();
for (int i = 0, n = k.length; i < n; i++) {
for (int j = 0, m = a.length; j < m; j++) {
a[j] = (char)(a[j] ^ k[i]);
}
}
return new String(a);
}
private static String rmRepeated(String s) {
char[] c = s.toCharArray();
int len = c.length;
int k = 0;
int count = 0;
for (int i = 0; i < len; i++) {
k = i + 1;
while (k < len - count) {
if (c[i] == c[k]) {
for (int j = k; j < len - 1; j++) {
c[j] = c[j + 1];
}
count++;
k--;
}
k++;
}
}
return new String(c, 0, len - count);
}
private static String encode(String str) {
try {
byte[] bytes = str.getBytes("UTF-8");
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (int i = 0, n = bytes.length; i < n; i++) {
sb.append(HEX_STRING.charAt((bytes[i] & 0xF0) >> 4));
sb.append(HEX_STRING.charAt((bytes[i] & 0x0F) >> 0));
}
return sb.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "";
}
}
public static String encrypt(String inStr, String secretKey) {
String hexStr = convert(inStr, secretKey);
return encode(hexStr);
}
}
PHP代码:
<?php
$hexString = "0123456789ABCDEF";
function convert($inStr, $secretKey) {
$s = utf8_encode($inStr);
$a = str_split($s);
$k = str_split(rmRepeated($secretKey));
foreach ($k as $kk) {
foreach ($a as &$aa) {
$aa = $aa ^ $kk;
}
}
return implode("", $a);
}
function rmRepeated($s) {
$c = str_split($s);
$len = count($c);
$count = 0;
for ($i = 0; $i < $len; $i++) {
$k = $i + 1;
while ($k < $len - $count) {
if ($c[$i] == $c[$k]) {
for ($j = $k; $j < $len - 1; $j++) {
$c[$j] = $c[$j + 1];
}
$count++;
$k--;
}
$k++;
}
}
return implode("", array_slice($c, 0, $len - $count));
}
function encode($str) {
$bytes = unpack('C*', $str);
$out = "";
foreach ($bytes as $byte) {
$out .= $GLOBALS['hexString'][($byte & 0xF0) >> 4];
$out .= $GLOBALS['hexString'][$byte & 0x0F];
}
return $out;
}
function encrypt($inStr, $secretKey) {
$hexStr = convert($inStr, $secretKey);
return encode($hexStr);
}
$s = "12bvdde`一二三四五六七八,1234@¥#%&*()-=|+_}{[]/.,;:,.>》》。,《dkfjaskfaskdjfkdasj";
$enc = encrypt($s, "f8ee541137a2aa381abaac17886653ba");
echo "加密的:" . $enc . "\n"; // 加密的:6C0CC5CFA06F74E2A982A2385AC1A834D98EB6C6FEFBD10B8E1EDF6CE912C911CB0427C08CB4CA9C6A13C6143E4721BBE97C3DFF6A1C51D1EBFBCD288DFD7AC
?>
没有什么字符串,只有二进制字节数组。
注意区别汉字编码(GBK/UTF8)
注意区别有符号/无符号。