2011-03-26 116 views
0

尝试使用AES和RSA创建安全连接时,我发现当我尝试将密钥转换为字符串以通过网络发送时,再次转换为字节[]。值改变了。你可以看到下面涉及的代码来理解我的想法。将字节[]转换为字符串,然后返回字节时出现问题

public class test { 
    public static String asHex (byte buf[]) { 
     StringBuffer strbuf = new StringBuffer(buf.length * 2); 
     int i; 

     for (i = 0; i < buf.length; i++) { 
     if (((int) buf[i] & 0xff) < 0x10) 
     strbuf.append("0"); 

     strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); 
     } 

     return strbuf.toString(); 
    } 

public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException { 


    KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
kgen.init(128); 

SecretKey skey = kgen.generateKey(); 
byte[] raw = skey.getEncoded(); 

String r = new String(raw,"UTF-8"); 

System.out.println(asHex(raw));// prints for example fd812245c9bfc4106294d51bf27e3796 

byte[] t = r.getBytes("UTF-8"); 

System.out.println(asHex(t)); // prints for example : efbfbd2245c9bfefbfbd1062efbfbdefbfbd1befbfbd7e37efbfbd 

    } 
} 
+0

我不确定这是否会导致您的问题,但使用UTF-8作为编码可能不是一个好主意,因为并非每个字节序列都是有效的UTF-8字符串。我会使用像ISO8859-1这样的单字节编码。 – 2011-03-26 14:55:27

+0

@Philipp:使用任何*编码假设它是真正的编码文本是一个非常糟糕的主意。 – 2011-03-26 15:00:25

回答

0

这就是为什么你应该使用十六进制(或更好的base64)表示传输字节数组。

+0

我已经使用base64,但它使数据更大.. – moataz 2011-03-26 15:07:43

+1

@moataz这是更大的一个原因 - 它可以编码和解码没有歧义。如果流量是个问题,你可以使用gzip压缩它 – Bozho 2011-03-26 15:22:39

4

这是因为将原始字节数组转换为UTF-8字符串。由于不是每个字节序列都是有效的UTF-8字符串,因此字符串构造函数可以在转换为有效字符串类型的同时对其进行修改。

4

当您使用String(byte[], String)构造函数时,您会说:“这是某些文本的编码版本,并且这是编码。”

这就是不是这里的情况。你没有编码文本 - 你有不透明的二进制数据。这根本不是文本数据。使用Base64将其安全地转换为纯ASCII字符串。有一个public domain Java encoder/decoder你可以使用。

+1

我认为编码ISO8859-1将解决问题 – moataz 2011-03-26 15:08:10

+2

@moataz:它*可能*取决于你以后对字符串做了什么,但这是一个根本*错误的方法。只要使用Base64就像世界其他地方所做的那样,当他们想要在文本中表示不透明的二进制数据时。 – 2011-03-26 15:27:18

相关问题