如何解决C#和Java之间的Diffie-Hellman算法
我有 C# 和 Java 的控制台应用程序。它们都为 Eliptic 曲线 Diffie-Hellman 算法生成公钥和私钥。公钥在 base64 中加密,然后在控制台中打印。然后我将公钥从 c# 粘贴到 java 程序中,反之亦然。 不幸的是,最终必须相同的派生密钥不同。 似乎算法的配置是相同的,没有例外。
C#:
static void Main(string[] args)
{
ECDiffieHellmanCng eCDiffie = new ECDiffieHellmanCng(256);
eCDiffie.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
eCDiffie.HashAlgorithm = Cngalgorithm.Sha256;
byte[] myPublicKey = eCDiffie.ExportSubjectPublicKeyInfo(); //export in x509 format
String myPublicKeyBase64 = Convert.ToBase64String(myPublicKey);
Console.WriteLine(myPublicKeyBase64);
string otherKey = Console.ReadLine(); // here paste public key in console from Java
byte[] otherKeyFromBase64 = Convert.FromBase64String(otherKey);
ECDiffieHellmanCng eCDiffie2 = new ECDiffieHellmanCng(256);
eCDiffie2.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
eCDiffie2.HashAlgorithm = Cngalgorithm.Sha256;
int some = 0;
eCDiffie2.ImportSubjectPublicKeyInfo(otherKeyFromBase64,out some);
byte[] otherKeyDecoded = eCDiffie2.PublicKey.ToByteArray();
CngKey k = CngKey.Import(otherKeyDecoded,CngKeyBlobFormat.EccpublicBlob);
byte[] derivedKey = eCDiffie.DeriveKeyMaterial(k);
String derivedKeyBase64 = Convert.ToBase64String(derivedKey);
Console.WriteLine("Derived key: ");
Console.WriteLine(derivedKeyBase64);
}
Java:
public static void main(String[] args) throws NoSuchAlgorithmException,InvalidKeyException,InvalidKeySpecException {
// Generate ephemeral ECDH keypair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(256);
KeyPair kp = kpg.generateKeyPair();
byte[] ourPk = kp.getPublic().getEncoded(); //public key in x509 format
// display our public key
byte[] ourPublicKeyBase64 = Base64.getEncoder().encode(ourPk);
System.out.println(String.format("Public Key: %s",new String(ourPublicKeyBase64)));
// Read other's public key:
Scanner in = new Scanner(system.in);
String oth = in.nextLine(); // here paste in console public key C#
byte[] otherPk = Base64.getDecoder().decode(oth);
KeyFactory kf = KeyFactory.getInstance("EC");
X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(otherPk);
PublicKey otherPublicKey = kf.generatePublic(pkSpec);
// Perform key agreement
KeyAgreement ka = KeyAgreement.getInstance("ECDH");
ka.init(kp.getPrivate());
ka.doPhase(otherPublicKey,true);
// Read shared secret
byte[] sharedSecret = ka.generateSecret();
// Derive a key from the shared secret and both public keys
MessageDigest hash = MessageDigest.getInstance("SHA-256");
hash.update(sharedSecret);
// Simple deterministic ordering
List<ByteBuffer> keys = Arrays.asList(ByteBuffer.wrap(ourPk),ByteBuffer.wrap(otherPk));
Collections.sort(keys);
hash.update(keys.get(0));
hash.update(keys.get(1));
byte[] derivedKey = hash.digest();
byte[] derivedKeyBase64 = Base64.getEncoder().encode(derivedKey);
System.out.println(String.format("Derived key: %s",new String(derivedKeyBase64)));
}
解决方法
您的 Java
代码做了一些额外的工作来获取派生密钥。只需删除以下几行,您将获得与 С#
代码中相同的密钥:
// Simple deterministic ordering
List<ByteBuffer> keys = Arrays.asList(ByteBuffer.wrap(ourPk),ByteBuffer.wrap(otherPk));
Collections.sort(keys);
hash.update(keys.get(0));
hash.update(keys.get(1));
以下是完整的 Java
代码:
public static void main(String[] args) throws Exception {
// Generate ephemeral ECDH keypair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(256);
KeyPair kp = kpg.generateKeyPair();
byte[] ourPk = kp.getPublic().getEncoded(); //public key in x509 format
// Display our public key
byte[] ourPublicKeyBase64 = Base64.getEncoder().encode(ourPk);
System.out.println(String.format("Public Key: %s",new String(ourPublicKeyBase64)));
// Read other's public key:
Scanner in = new Scanner(System.in);
String oth = in.nextLine(); // here paste in console public key C#
byte[] otherPk = Base64.getDecoder().decode(oth);
KeyFactory kf = KeyFactory.getInstance("EC");
X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(otherPk);
PublicKey otherPublicKey = kf.generatePublic(pkSpec);
// Perform key agreement
KeyAgreement ka = KeyAgreement.getInstance("ECDH");
ka.init(kp.getPrivate());
ka.doPhase(otherPublicKey,true);
// Read shared secret
byte[] sharedSecret = ka.generateSecret();
// Derive a key from the shared secret
MessageDigest hash = MessageDigest.getInstance("SHA-256");
hash.update(sharedSecret);
byte[] derivedKey = hash.digest();
byte[] derivedKeyBase64 = Base64.getEncoder().encode(derivedKey);
System.out.println(String.format("Derived key: %s",new String(derivedKeyBase64)));
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。