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