最近看了下数据流加密。
最初项目组采用了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变为负数。
近期评论