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

Nou*_*MRI 17 java cryptography jwe ecdh

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

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

  • "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 Compact Serialization根据JWS(RFC 7515)生成完整JSON对象的数字签名.此版本规范支持的参数值为:

  • "alg":PS256或ES256
  • "x5c":X.5C v3:Cert(MyPb)以及可选的链接证书

根据我的理解,ECDH将生成一个密钥.在共享我的短暂公钥(QT)之后,SDK生成相同的密钥,因此我们以后可以交换使用相同密钥加密的JWE消息.

JSON {"MyPublicKey":"QT","SDKPublicKey":"QC"}将被签名并发送,但我不明白我将如何使用apvepk,因为这些标题参数在JWE中使用而不是在第一个JWS将被共享.

在相同的规范中,他们谈论这些JWE消息,但他们没有这些apv和epk参数.

根据JWE(RFC 7516)使用SDK使用的相同"enc"算法加密JSON对象,获得的CEK由"kid"和JWE Compact Serialization识别.此版本规范支持的参数值为:

  • "alg":dir
  • "enc":A128CBC-HS256或A128GCM
  • "kid":交易ID
  • 所有其他参数:不存在

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

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

ban*_*'14 5

这两个apv(协议PartyVInfo)和epk(短暂公开密钥)是可选的,这样他们就可以以多种方式使用.例如,您可以使用apv反映SDK版本.它们被添加到JWE标头中.

您可以在此处阅读有关Nimbus中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);
    }
}
Run Code Online (Sandbox Code Playgroud)

而不是EncryptionMethod.A128GCM你可以EncryptionMethod.A128CBC-HS256在你的规范中使用.apvepk添加到内部构建器中的JWEHeader.可以在JWEHeader.Builder和ECKey的构造函数中选择其他参数.我使用了ECDH-ES算法,A128GCM加密方法,P-256曲线(椭圆曲线默认为ECKey生成),事务ID是一个字符串.我选择了没有任何清晰图案的其他参数.对于该示例,KeyStore的初始化将过于宽泛.加密只是JWE可以做的一件事,在签名和其他方面.