ECDH 加密,菜鸟问题

本人纯属虚构 发布于 2015/06/04 20:11
阅读 3K+
收藏 2


本人菜鸟

ECDH原理大致了解下

java在ECDH有一个开源的包 bcprov-jdk15on-150.jar 下面有下载地址

我想问知道能不能固定下面的变量 "ecdhkey" 让加密结果也固定

意思也就是说 如果我知道这个"ecdhkey" 能计算出结果吗?


import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.Security;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPublicKeySpec;

import javax.crypto.KeyAgreement;

import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.ECPointUtil;
import org.bouncycastle.math.ec.ECPoint;
import sun.security.ec.NamedCurve;

public class ECDHTest {

	/**
	 * 在控制台打印字节
	 * 
	 * @param bArray
	 * @return
	 */
	public static final String printBytesToHexString(byte[] bArray) {
		String byteStr = bytesToHexString(bArray);
		StringBuffer temp = new StringBuffer();
		for (int i = 0; i < byteStr.length(); i++) {
			if (i != 0 && i % 2 == 0) {
				temp.append(" " + byteStr.charAt(i));
			} else {
				temp.append(byteStr.charAt(i));
			}
		}
		return temp.toString();
	}

	/**
	 * 把字节数组转换成16进制字符串
	 * 
	 * @param bArray
	 * @return
	 */
	public static final String bytesToHexString(byte[] bArray) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		for (int i = 0; i < bArray.length; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}

	/**
	 * 把16进制字符串转换成字节数组
	 * 
	 * @param hex
	 * @return
	 */
	public static byte[] hexStringToByte(String hex) {
		if (hex.length() % 2 != 0) {
			hex = "0" + hex;
		}
		int len = (hex.length() / 2);
		byte[] result = new byte[len];
		char[] achar = hex.toCharArray();
		for (int i = 0; i < len; i++) {
			int pos = i * 2;
			result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
		}
		return result;
	}

	private static byte toByte(char c) {
		byte b = (byte) "0123456789ABCDEF".indexOf(c);
		return b;
	}

	public static void main(String[] args) {
		try {
			// 711
			byte[] serverPBK = new byte[] { 0x04, (byte) 0x92, (byte) 0x8D, (byte) 0x88, 0x50, 0x67, 0x30, (byte) 0x88, (byte) 0xB3, 0x43, 0x26,
					0x4E, 0x0C, 0x6B, (byte) 0xAC, (byte) 0xB8, 0x49, 0x6D, 0x69, 0x77, (byte) 0x99, (byte) 0xF3, 0x72, 0x11, (byte) 0xDE,
					(byte) 0xB2, 0x5B, (byte) 0xB7, 0x39, 0x06, (byte) 0xCB, 0x08, (byte) 0x9F, (byte) 0xEA, (byte) 0x96, 0x39, (byte) 0xB4,
					(byte) 0xE0, 0x26, 0x04, (byte) 0x98, (byte) 0xB5, 0x1A, (byte) 0x99, 0x2D, 0x50, (byte) 0x81, (byte) 0x3D, (byte) 0xA8 };

			Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

			ECParameterSpec ecSpec = NamedCurve.getECParameterSpec("secp192k1");

			KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDH", "BC");
			SecureRandom sr = new SecureRandom();

			// 取消掉这个注释后 结果倒是固定 不过不能得到想要的数据
			// sr.setSeed(hexStringToByte("02 D7 2D 3D".replace(" ", "")));

			keyGen.initialize(ecSpec, sr); // 公私钥 工厂
			KeyPair pair = keyGen.generateKeyPair(); // 生成公私钥
			BCECPublicKey cpk = (BCECPublicKey) pair.getPublic();
			ECPoint.Fp point = (ECPoint.Fp) cpk.getQ();
			System.out.println(pair.getPublic());

			// ecdhkey 当我先知道这个 ecdhkey 能不能把已知的值set进去 得到一个固定的结果???
			byte[] ecdhkey = point.getEncoded(true);
			System.out.println("ecdhkey: " + printBytesToHexString(ecdhkey));

			java.security.spec.ECPoint sp = ECPointUtil.decodePoint(ecSpec.getCurve(), serverPBK);
			KeyFactory kf = KeyFactory.getInstance("ECDH", "BC");
			ECPublicKeySpec pubSpec = new ECPublicKeySpec(sp, ecSpec);
			ECPublicKey myECPublicKey = (ECPublicKey) kf.generatePublic(pubSpec);

			KeyAgreement agreement = KeyAgreement.getInstance("ECDH", "BC");
			agreement.init(pair.getPrivate());
			agreement.doPhase(myECPublicKey, true);
			System.out.println("secret: " + printBytesToHexString(agreement.generateSecret()));

			byte[] xx = agreement.generateSecret();
			byte[] result = new byte[16];
			// 只需要前面16个字节
			System.arraycopy(xx, 0, result, 0, 16);

			// 打印最后的密文
			System.out.println("result: " + printBytesToHexString(result));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


所需jar包下载地址:

http://polydistortion.net/bc/download/bcprov-jdk15on-150.jar

加载中
0
本人纯属虚构
本人纯属虚构

今天有人问我这个问题 还是补充一下吧


ECDH算法流程


1.客户端根据ECDH规则随机生成私匙PrivateKey和公匙PublicKey(X,Y)

2.Stkey(0x19) = PublicKey.X

暂且把stkey叫做客户端生成的公匙

stkey会发送给TX

这里还有一点不明白的地方,因为发送给腾讯的只有0x19字节,而生成的PublicKey是一个点,发送给腾讯的只是点上的X,而Y没有发给TX,相当于是一个不完整的公匙。

另外ecdh的第一个字节表示压缩方式,以0x02或者0x03开头。

3.TX根据自己的私匙和客户端发送过来的stkey在服务器生成decodekey

4.而客服端也会根据自己的私匙和腾讯"发送"公匙生成同样的decodekey

为什么发送加上引号呢?因为没有发送这个过程,腾讯早就算好了,并且把这个公匙预置在了客户端,客户端直接取了这个公匙计算decodekey!

 

注:腾讯的服务器私匙是不可见的,并且是固定的,所以内置在客户端的公匙也就是固定的。

0
本人纯属虚构
本人纯属虚构

被TX误导了

上面是无解的

结贴...

0
A
Arvin____
NamedCurve这个类为什么找不到啊
0
凡有度
凡有度

请问java ecdh  import sun.security.ec.NamedCurve; 这个包哪里来的

返回顶部
顶部