最近看了下数据流加密。
最初项目组采用了rc4加密,但双方密钥直接明文存储。被确解的可能性很大。
看了云风介绍了,使用dh进行rc4密钥交换,遂动手进行处理。
dh是非对称加密算法,用于交换密钥。
服务器使用java
客户端使用c#
采了几个坑:
1、java中pubkey使用X509格式存储,prikey使用PKCS8格式存储,如果要取到原始明文,需要使用:
public static Map<String, BigInteger> initKeyRaw() {
try {
KeyPairGenerator gen = KeyPairGenerator.getInstance("DH");
gen.initialize(KEY_SIZE);
KeyPair keyPair = gen.generateKeyPair();
DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();
Map<String, BigInteger> ret = Maps.newHashMap();
ret.put("x", dhPrivateKey.getX());
ret.put("y", dhPublicKey.getY());
ret.put("p", dhPublicKey.getParams().getP());
ret.put("g", dhPublicKey.getParams().getG());
return ret;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Map<String, BigInteger> initKeyRaw(BigInteger y, BigInteger p, BigInteger g) {
try {
KeySpec keySpec = new DHPublicKeySpec(y, p, g);
KeyFactory keyFactory = KeyFactory.getInstance("DH");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
DHParameterSpec dhParamSpec = ((DHPublicKey) pubKey).getParams();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyFactory.getAlgorithm());
keyPairGenerator.initialize(dhParamSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();
Map<String, BigInteger> ret = Maps.newHashMap();
ret.put("x", dhPrivateKey.getX());
ret.put("y", dhPublicKey.getY());
ret.put("p", dhPublicKey.getParams().getP());
ret.put("g", dhPublicKey.getParams().getG());
return ret;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
2、第二个坑
在网上找了一个c#版的dh源码,如果发现两边生成的key怎么都不对,最后定位到,java 中的biginteger是带符号位的。c#版中的biginteger是无符号位的,计算结果当然就不正确了。
我的解决方式是在java中转为biginterger前,添加“00”,这样避免了biginteger变为负数。
0 条评论。