当前位置:编程学习 > JAVA >>

DHPublicKey与byte[]转换的问题

背景:
网络上经常采用Diffie-Hellman算法来交换密钥。通讯的双方首先共享2个公开数字:p和g。其中p是一个大质数,g通常等于2。则\( Z_p=\{a=g^n \pmod{p}, n \in N \} \) 构成一个整数群。
密钥的生成方法:
\(Z_p\)中选取一个随机数x,然后计算\( y=g^x \)。那么x,y构成一个keypair。x是私钥,y是公钥。
那么每个人只需要把自己的公钥发出去,然后通信的时候选取一个对称加密算法,利用\(y^x\)作为通信的加密密钥即可。其中x是自己的私钥,y是对方的公钥。
实际在用JAVA实现的时候:
公钥和私钥可以通过java.security.KeyPairGenerator生成。
//DH是算法名,SunJCE是Java Security API的Provider名,此处使用JDK自带的的SunJCE。
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH","SunJCE");
然后初始化KeyPairGenerator 这时需要传入一个java.security.spec.AlgorithmParameterSpec对象。
kpg.initialize(MODP_GROUP2);
MODP_GROUP2对象是这么来的:
StringBuffer sb = new StringBuffer();
sb.append("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1");
sb.append("29024E088A67CC74020BBEA63B139B22514A08798E3404DD");
sb.append("EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245");
sb.append("E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED");
sb.append("EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381");
sb.append("FFFFFFFFFFFFFFFF");
BigInteger prime = new BigInteger(sb.toString(), 16);
BigInteger generator = BigInteger.valueOf(2);
MODP_GROUP2 = new DHParameterSpec(prime, generator);
它描述了DH算法所需要用到的p和g等于几。我在这里所用的prime来自于rfc2412的OAKLEY Key Group 2。
有了上述信息,就可以开始生成keypair:
KeyPair aliceDHKeyPair = kpg.generateKeyPair();
DHPublicKey dp = (DHPublicKey) aliceDHKeyPair.getPublic();
下面的问题是,怎么把DHPublicKey发出去?
首先DHPublicKey自带有一个getEncoded()方法,默认是采用X.509方式编码。但是这种编码方式,会把p,g,y都写入进入byte[]中。这对于实际应用来说,根本不必要啊,我只需要公钥(y)就行了啊!
于是我就把Y拿出来,然后转byte[]。
final int length=dp.getY().bitLength();
byte[] ret = dp.getY().toByteArray();        
if(length==1024)
     ret=Arrays.copyOfRange(ret, 1, ret.length);
这其中多了一层Array.copyOfRange是因为,BigInteger的toByteArray()方法,会把符号位也写入最终结果中。那么,如果Y恰好是1024位的,最终就会得到一个129字节的byte[](其中第一个字节是0)
可是当我把这个byte[]收到时候再转成PubicKey,发现跟发送前不一样了:
KeyFactory keyFactory = KeyFactory.getInstance("DH", PROVIDER);
BigInteger y = new BigInteger(1, ret);
DHPublicKeySpec spec = new DHPublicKeySpec(y, MODP_GROUP2.getP(),
                MODP_GROUP2.getG());
DHPublicKey dp2 = (DHPublicKey) keyFactory.generatePublic(spec);
Assert.assertEquals(dp, dp2); //Always Fail
这个fail的原因在于,尽管p、g、Y都相等,但是l不相等。非常令我崩溃。发送前,DHPublicKey 的l=512,发送后用keyFactory得到的DHPublicKey 的l=0。JDK文档中对l的解释是“the size in bits of the random exponent (private value)”。但是我不知道为什么即使我在DHParameterSpec将它设置成512,得到的Y依然是1024字节。我在想这个要不要紧,要么忍了吧。改改test case。
 

 作者 snnn

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,