当前位置: 首页 > 知识库问答 >
问题:

在Java中实现Diffie-Hellman密钥交换

包修贤
2023-03-14

我试图用Java实现Diffie-Hellman密钥交换,但我很难理解规范:

根据JWA(RFC 7518),在直接密钥协商模式下,使用曲线P-256、dT和QC完成Diffie-Hellman密钥交换过程,作为本地机制,产生一对由事务ID标识的CEK(每个方向一个)。本规范版本支持的参数值为:

  • alg: ECDH-ES
  • "apv": SDK参考号
  • epk:QC,JSON Web Key(JWK)格式
  • {"kty":"EC""crv":"P-256"}
  • 所有其他参数:不存在
  • CEK:"kty": oct-256位

创建包含以下数据的JSON对象作为要签名的JWS负载:

{“MyPublicKey”:“QT”,“SDKPublicKey”:“QC”}

根据JWS(RFC 7515)使用JWS Compact序列化生成完整JSON对象的数字签名。本规范版本支持的参数值为:

  • “alg”:PS256或ES256
  • “x5c”:X.5C v3:Cert(MyPb)加上可选的链接证书

据我了解,ECDH将生成一个密钥。共享我的临时公钥(QT)后,SDK生成相同的密钥,因此我们可以稍后交换使用相同密钥加密的JWE消息。

JSON{"MyPublicKey":"QT"、"SDKPublicKey":"QC"}将被签名并发送,但是我不明白如何使用apv和epk,因为这些头参数在JWE中使用,而不是在第一个要共享的JWS中。

在同一个规范中,他们谈论这些JWE消息,但是他们没有这些apv和epk参数。

根据JWE(RFC 7516)使用SDK使用的相同“enc”算法加密JSON对象,CEK由“kid”和JWE Compact序列化标识。本规范版本中支持的参数值为:

  • "alg": dir
  • "enc": A128CBC-HS256或A128GCM
  • "孩子":事务ID
  • 所有其他参数:不存在

我还阅读了RFC 7518中的示例,其中我可以看到使用的头参数apv和epk,但我不确定哪个头参数,JWE的还是JWS的?

任何关于如何使用nimbus jose jwt或任何其他java库实现这一点的想法都会非常有用。谢谢

共有3个答案

姚浩歌
2023-03-14

我能够为A128CBC-HS256生成密钥。然而,在128GCM中仍然没有成功。使用帮助nimbus jose库添加A128CBC-HS256的工作示例。以下代码仅用于密钥生成。

还请注意,我覆盖了nimbus jose类以供使用。希望能有帮助。

private void generateSHA256SecretKey(AREQ areq, ECKey sdkPubKey, KeyPair acsKeyPair) throws Exception {

        // Step 4 - Perform KeyAgreement and derive SecretKey
        SecretKey Z = CustomECDH.deriveSharedSecret(sdkPubKey.toECPublicKey(), (ECPrivateKey)acsKeyPair.getPrivate(), null);

        CustomConcatKDF concatKDF = new CustomConcatKDF("SHA-256");

        String algIdString = "";
        String partyVInfoString = areq.getSdkReferenceNumber();
        int keylength = 256; //A128CBC-HS256            

        byte[] algID = CustomConcatKDF.encodeDataWithLength(algIdString.getBytes(StandardCharsets.UTF_8));
        byte[] partyUInfo = CustomConcatKDF.encodeDataWithLength(new byte[0]);          
        byte[] partyVInfo = CustomConcatKDF.encodeDataWithLength(partyVInfoString.getBytes(StandardCharsets.UTF_8));
        byte[] suppPubInfo = CustomConcatKDF.encodeIntData(keylength);
        byte[] suppPrivInfo = CustomConcatKDF.encodeNoData();

        SecretKey derivedKey = concatKDF.deriveKey(
            Z,
            keylength,
            algID,
            partyUInfo,
            partyVInfo,
            suppPubInfo,
            suppPrivInfo);

        System.out.println("Generated SHA256 DerivedKey : "+SecureUtils.bytesToHex(derivedKey.getEncoded()));       
    }
隆飞驰
2023-03-14

Nimbus(以及Jose4j)不是实现规范的最佳选择(我猜它是3D安全2. x. x)。

这些库不返回内容加密密钥,而是根据JWE规范使用它加密或解密消息。

我发现Apache CXF Jose库作为JWE/JWS/JWK实现做得很好。除了生成短暂的密钥对。但这可以很容易地用充气城堡来完成:

Security.addProvider(new BouncyCastleProvider());
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec(JsonWebKey.EC_CURVE_P256);
KeyPairGenerator g = KeyPairGenerator.getInstance(ALGORITHM_SIGNATURE_EC, "BC");
g.initialize(ecGenSpec, new SecureRandom());
KeyPair keyPair = g.generateKeyPair();

可以使用以下代码生成内容加密密钥:

byte[] cek = JweUtils.getECDHKey(privateKey, publicKey, null, SDKReferenceNumber, "", 256);

并用于加密消息以获得JWE紧凑表示:

JweEncryption jweEncryption = JweUtils.getDirectKeyJweEncryption(cek, contentAlgorithm);
JweHeaders head = new JweHeaders();
head.setHeader(JoseConstants.HEADER_KEY_ID, keyId);
String encrypted = jweEncryption.encrypt(contentToEncrypt.getBytes(StandardCharsets.UTF_8), head);

或解密:

JweCompactConsumer compactConsumer = new JweCompactConsumer(encrypted);
JweHeaders head = compactConsumer.getJweHeaders();
JweDecryption jweDecryption = JweUtils.getDirectKeyJweDecryption(cek, head.getContentEncryptionAlgorithm());
JweDecryptionOutput out = jweDecryption.decrypt(encrypted);
String decrypted = out.getContentText();
晏永康
2023-03-14

apv(协议方yvinfo)和epk(临时公钥)都是可选的,因此它们可以以多种方式使用。例如,您可以使用apv来反映SDK版本。它们被添加到JWE标题中。

你可以在这里阅读更多关于光环JWE的信息

使用Nimbus JOSE的示例如下:

import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.nimbusds.jose.*;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.jwk.KeyOperation;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.util.Base64;
import com.nimbusds.jose.util.Base64URL;

public class Security {

    public void generateJWE() throws JOSEException, URISyntaxException {
        JWEHeader jweHeader = buildJWEHeader(new Base64URL("202333517"), buildECKey());
        JWEObject jweObject = new JWEObject(jweHeader, new Payload("Hello World!"));
    }

    private JWEHeader buildJWEHeader(Base64URL apv, ECKey epk) {
        JWEHeader.Builder jweBuilder = new JWEHeader.Builder(JWEAlgorithm.ECDH_ES, EncryptionMethod.A128GCM);
        jweBuilder.agreementPartyVInfo(apv);
        jweBuilder.ephemeralPublicKey(epk);
        return jweBuilder.build();
    }

    private ECKey buildECKey() throws URISyntaxException {
        Set<KeyOperation> keyOperations = new HashSet<>();
        keyOperations.add(KeyOperation.ENCRYPT);
        String transactionID = "73024831";
        URI x5u = new URI("https//website.certificate");
        KeyStore keystore = null; //initialize it
        List<Base64> x5c = new ArrayList<>();
        return new ECKey(Curve.P_256, new Base64URL("x"), new Base64URL("y"), KeyUse.ENCRYPTION, keyOperations, Algorithm.NONE, transactionID, x5u, new Base64URL("x5t"), new Base64URL("x5t256"), x5c, keystore);
    }
}

而不是加密方法。A128GCM可以使用Encryptionmethod。A128CBC-HS256与您的规范相同。apvepk被添加到JWEHeader内部的构建器中。其他参数可以在JWEHeader的构造函数中选择。生成器和ECKey。我用的是ECDH-ES算法,A128GCM加密方法,P-256曲线(ECKey生成中默认为椭圆曲线),事务ID为字符串。我选择了其他参数,没有任何明确的模式。KeyStore的初始化对于示例来说过于宽泛。在签名和其他操作中,加密只是JWE可以做的一件事。

 类似资料:
  • 我正在Java的一个个人项目中工作,该项目涉及通过不安全的通道发送敏感数据。我需要知道如何实现Diffie Hellman密钥交换(DHKE)在java使用其库。我知道关于它的所有密码理论,所以不需要深入细节,我只需要一个非常基本的实现,所以我可以让两个程序共享一个密钥。我从java2s.com得到了这个例子,但它并不完整: 我该怎么做呢?有人能帮我完成剩下的代码吗?

  • 在Diffie Hellman密钥交换过程中,如果中间的人能够得到素数“p”和生成器“g”的值。他现在能破译私钥或者生成的共享秘密秘密吗?

  • 我正在尝试将DHE_DSS实现到Go的Crypto/TLS包中。不幸的是,我似乎无法使PreMasterSecret(Z)相同,我的基本工作流程是: 提取P、G、YS 使用提供的数字签名进行验证 null 以下是我更改的一个补丁: https://08766345559465695203.googlegroups.com/attach/48587532C74B4348/crypto.patch?p

  • 因为这是我正在生成的一个自签名证书,所以我认为我做错了什么。 我首先创建一个根CA证书,并传入私钥来签署我的证书。 方法返回true,我读到的这个值可能返回假阳性。

  • 本文向大家介绍迪菲-赫尔曼密钥交换(Diffie–Hellman)算法原理和PHP实现版,包括了迪菲-赫尔曼密钥交换(Diffie–Hellman)算法原理和PHP实现版的使用技巧和注意事项,需要的朋友参考一下 迪菲-赫尔曼(Diffie–Hellman)是一个可以让双方在不安全的公共信道上建立秘钥的一种算法,双方后期就可以利用这个秘钥加密(如RC4)内容。 迪菲-赫尔曼(Diffie–Hellm

  • 我有一个应用程序,它是一个SSH客户端,支持以下协商的关键算法。 diffie-hellman-group-exchange-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256 我没有更改SSH客户端的选项,所以我正在尝试解决SSH服务器上的问题,它正在使用Twisted。SSH服务器实际上是在Kippo蜜罐中