我正在尝试在 Java 中创建一个非常简单的密钥交换。在代码和输出之后有问题:
public class Blergh {
public static KeyPair genKeyPair512() {
try {
AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator
.getInstance("DH");
paramGen.init(512);
BigInteger g = new BigInteger(
"7961C6D7913FDF8A034593294FA52D6F8354E9EDFE3EDC8EF082D36662D69DFE8CA7DC7480121C98B9774DFF915FB710D79E1BCBA68C0D429CD6B9AD73C0EF20",
16);
BigInteger p = new BigInteger(
"00AC86AB9A1F921B251027BD10B93D0A8D9A260364974648E2543E8CD5C48DB4FFBEF0C3843465BA8DE20FFA36FFAF840B8CF26C9EB865BA184642A5F84606AEC5",
16);
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH");
final DHParameterSpec dhSpec = new DHParameterSpec(p, g, 511);
keyGen.initialize(dhSpec);
return keyGen.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
public static byte[] genSharedSecretKey(KeyPair keyPair,
byte[] bytesPeerPublicKey) {
PrivateKey privateKey = keyPair.getPrivate();
try {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(
bytesPeerPublicKey);
KeyFactory keyFact = KeyFactory.getInstance("DH");
PublicKey peerPublicKey = keyFact.generatePublic(x509KeySpec);
KeyAgreement ka;
ka = KeyAgreement.getInstance("DH");
ka.init(privateKey);
ka.doPhase(peerPublicKey, true);
String algorithm = "AES";
SecretKey secretKey = ka.generateSecret(algorithm);
return secretKey.getEncoded();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
public static void main(String argv[]) {
KeyPair akp = genKeyPair512();
KeyPair bkp = genKeyPair512();
System.out.println("Ali pub key: "
+ toRawHex(akp.getPublic().getEncoded()));
System.out.println("Bob pub key: "
+ toRawHex(bkp.getPublic().getEncoded()));
System.out.println("Ali pri key: "
+ toRawHex(akp.getPrivate().getEncoded()));
System.out.println("Bob pri key: "
+ toRawHex(bkp.getPrivate().getEncoded()));
byte[] apk = akp.getPublic().getEncoded();
byte[] bpk = bkp.getPublic().getEncoded();
byte[] as = genSharedSecretKey(akp, bpk);
byte[] bs = genSharedSecretKey(bkp, apk);
}
}
例如,它生成输出:
Ali pub key: 3081DF30819706092A864886F70D010301308189024100AC86AB9A1F921B251027BD10B93D0A8D9A260364974648E2543E8CD5C48DB4FFBEF0C3843465BA8DE20FFA36FFAF840B8CF26C9EB865BA184642A5F84606AEC502407961C6D7913FDF8A034593294FA52D6F8354E9EDFE3EDC8EF082D36662D69DFE8CA7DC7480121C98B9774DFF915FB710D79E1BCBA68C0D429CD6B9AD73C0EF20020201FF03430002403BBCBF4052CD1CEF7A580A919AF75186CE0A624BC93AA47922C3822CE60A8CD10CE98550ABCA2D39DA2F09903C3D761B9A1C4AED185934FE5D08AD0CD097AA86
Bob pub key: 3081DF30819706092A864886F70D010301308189024100AC86AB9A1F921B251027BD10B93D0A8D9A260364974648E2543E8CD5C48DB4FFBEF0C3843465BA8DE20FFA36FFAF840B8CF26C9EB865BA184642A5F84606AEC502407961C6D7913FDF8A034593294FA52D6F8354E9EDFE3EDC8EF082D36662D69DFE8CA7DC7480121C98B9774DFF915FB710D79E1BCBA68C0D429CD6B9AD73C0EF20020201FF03430002400F119BC06E53F8C33D3F7C16473D1F9E001FABF4D619930C34945AA2C6D0A00CB9B332CEAF2C0C2FB61D3F568B9263B69A152410237F4D793F8B571C34AB37B7
Ali pri key: 3081E102010030819706092A864886F70D010301308189024100AC86AB9A1F921B251027BD10B93D0A8D9A260364974648E2543E8CD5C48DB4FFBEF0C3843465BA8DE20FFA36FFAF840B8CF26C9EB865BA184642A5F84606AEC502407961C6D7913FDF8A034593294FA52D6F8354E9EDFE3EDC8EF082D36662D69DFE8CA7DC7480121C98B9774DFF915FB710D79E1BCBA68C0D429CD6B9AD73C0EF20020201FF0442024043BA0B3C73EB7482B80DE98FA81A7E50B0DC2F5786CA62285655BD36CE012C056545DE5EED65736D9135EC9CD5148F8D68FF3C7B5CC62B2A1F7649698B26D1BE
Bob pri key: 3081E102010030819706092A864886F70D010301308189024100AC86AB9A1F921B251027BD10B93D0A8D9A260364974648E2543E8CD5C48DB4FFBEF0C3843465BA8DE20FFA36FFAF840B8CF26C9EB865BA184642A5F84606AEC502407961C6D7913FDF8A034593294FA52D6F8354E9EDFE3EDC8EF082D36662D69DFE8CA7DC7480121C98B9774DFF915FB710D79E1BCBA68C0D429CD6B9AD73C0EF20020201FF04420240485DDD7F5BDECA92FEE30D9D15211D274BC0FF7838B8B51E7894263CA65DB4E394033CE3E2146C0CD0CA74E2DB0EF95D01EE0DC4011A3EC6A8EC61CC2FDC5A44
所以,我有一个主要问题和两个附加问题:
- 为什么 Alice 和 Bob 之间的密钥(私有和公共)有一半以上的字节是相等的?例如,Alice 的私有以开头,
3081E102010030819706092A...
Bob 的私有3081E102010030819706092A...
也以。 - 为什么
DHParameterSpec
使用 511 而不是 512 创建(至少在网络上的大多数示例中)? - 假设生成的密钥没有任何问题,我这里是否还有其他遗漏,或者此代码在通过互联网交换公钥时应该是安全的?
欢迎任何帮助。提前致谢。
编辑:第三个问题也适用于genSharedSecretKey()
(即整个代码),尽管我没有调用/显示输出,因为它是无关紧要的。