簡體   English   中英

C# 和 Java 之間的 Diffie-Hellman 算法

[英]Diffie-Hellman algorithm between C# and Java

我在 c# 和 Java 中有控制台應用程序。 它們都為橢圓曲線 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)));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM