首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于jose4j的ECDH + JWE加密/解密

基于jose4j的ECDH + JWE加密/解密
EN

Stack Overflow用户
提问于 2019-05-12 06:58:03
回答 1查看 3.3K关注 0票数 1

我正试图在Android (Java)中与JWE一起实现ECDH加密/解密。

我已经找到了jose4j尼姆布斯·何塞库,它们的目标是完成我所需要的一切,但它似乎比我想象的更具挑战性。

如果有人熟悉,那就是3D安全2.0.

规范中的

  • SDK =本地侧
  • DS =目录服务器(另一边)

接下来是规范:

  • 给定: P(DS) -一个EC公钥(以PEM格式提供,可转换为PublicKey或JWK)
  • 生成一个新的临时密钥对(Q(SDK),d(SDK))
  • 在直接密钥协商模式下,根据JWA (RFC7518)进行Diffie-Hellman密钥交换过程,使用曲线P-256、d(SDK)和P(DS)生成一个CEK。规范的这个版本中支持的参数值是:
    • "alg":ECDH-ES
    • "apv":DirectoryServerID
    • "epk":P(DS),inJSONWebKey(JWK)格式{"kty":"EC","crv":"P-256"}
    • 所有其他参数:不存在

  • CEK:“kty”:Oct-256位
  • 生成128位随机数据作为IV
  • 根据JWE (RFC7516)使用CEK和加密JSON对象。规范的这个版本中支持的参数值是:
    • "alg":dir
    • "epk":Q(SDK)为{"kty":"EC","crv":"P-256"}
    • “enc”:“A128CBC-HS256”或“A128GCM”
    • 所有其他参数:不存在

  • 如果算法是A128CBC-HS256,则使用完整的CEK,或者如果算法是A128GCM,则使用CEK的最左边的128位。
  • 删除临时密钥对(Q(SDK),d(SDK))
  • 将生成的JWE作为SDK加密数据提供给3DS服务器

如果有人已经实现了这个精确的规范,并可以共享代码,这将是辉煌的!

在jose4j示例中有一个使用ECDH创建JWT的示例:

C/jose4j/wiki/JWT%20 20Examples (最后一个示例,标题为“生成和使用嵌套(签名和加密) JWT")。

但这个例子并不是我所需要的。它创建一个令牌,而我需要加密文本。

从上面的规范中的“CEK:”kty:Oct-256位开始,我不知道该做什么。

下面是我使用Nimbus lib的代码(到目前为止):

代码语言:javascript
复制
public String nimbus_encrypt(String plainJson, ECPublicKey otherPublicKey, String directoryServerId) throws JOSEException {
    JWEHeader jweHeader = new JWEHeader(
            JWEAlgorithm.ECDH_ES,
            EncryptionMethod.A128CBC_HS256,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            Base64URL.encode(directoryServerId),
            null,
            0,
            null,
            null,
            null,
            null);

    JWEObject jwe = new JWEObject(jweHeader, new Payload(plainJson));
    jwe.encrypt(new ECDHEncrypter(otherPublicKey));
    String serializedJwe = jwe.serialize();

    Log.d("[ENCRYPTION]", "nimbus_encrypt: jwe = " + jwe.getHeader());
    Log.d("[ENCRYPTION]", "nimbus_encrypt: serializedJwe = " + serializedJwe);

    return serializedJwe;
}

这是nimbus输出:

"x":"AS0GRfAOWIDONXxaPR_4IuNHcDIUJPHbACjG5L7x-nQ","y":"xonFn1vRASKUTdCkFTwsl16LRmSe-bAF8EO4-mh1NYw"},:nimbus_encrypt=“RjAwMDAwMDAwMQ”,“enc”:“A128CBC-ES 256”,“alg”:“ECDH ES”} eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiJBUzBHUmZBT1dJRE9OWHhhUFJfNEl1TkhjRElVSlBIYkFDakc1TDd4LW5RIiwieSI6InhvbkZuMXZSQVNLVVRkQ2tGVHdzbDE2TFJtU2UtYkFGOEVPNC1taDFOWXcifSwiYXB2IjoiUmpBd01EQXdNREF3TVEiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiRUNESC1FUyJ9..Pi48b7uj3UilvVXKewFacg.0sx9OkHxxtZvkVm-IENRFw.bu5GvOAwcZxdxaDKWIBqwA = nimbus_encrypt: serializedJwe

下面是我使用jose4j库的代码(到目前为止,使用@的答案):

代码语言:javascript
复制
public String jose4j_encrypt(String plainJson, PublicKey otherPublicKey, String directoryServerId) throws JoseException {
    JsonWebEncryption jwe = new JsonWebEncryption();
    jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES);
    jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);

    jwe.setHeader(HeaderParameterNames.AGREEMENT_PARTY_V_INFO, Base64Url.encodeUtf8ByteRepresentation(directoryServerId));
    jwe.setKey(otherPublicKey);
    jwe.setPayload(plainJson);

    String serializedJwe = jwe.getCompactSerialization();
    Log.d("[ENCRYPTION]", "jose4j_encrypt: jwe = " + jwe);
    Log.d("[ENCRYPTION]", "jose4j_encrypt: serializedJwe = " + serializedJwe);

    return serializedJwe;
}

这是jose4j输出:

"x":"prvyhexJXDWvPQmPA1xBjY8mkHEbrEiJ4Dr-7_5YfdQ","y":"fPjw8UdfzgkVTppPSN5o_wprItKLwecoia9yrWi38yo",{“alg”:“EC ES”,"enc":"A128CBC-HS256","apv":"RjAwMDAwMDAwMQ","epk":{"kty":"EC",jose4j_encrypt“crv”:“P-256”} eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTEyOENCQy1IUzI1NiIsImFwdiI6IlJqQXdNREF3TURBd01RIiwiZXBrIjp7Imt0eSI6IkVDIiwieCI6InBydnloZXhKWERXdlBRbVBBMXhCalk4bWtIRWJyRWlKNERyLTdfNVlmZFEiLCJ5IjoiZlBqdzhVZGZ6Z2tWVHBwUFNONW9fd3BySXRLTHdlY29pYTl5cldpMzh5byIsImNydiI6IlAtMjU2In19..gxWYwFQSOqLk5HAgs7acdA.mUIHBiWpWSlQaEOJ_EZGYA.eiTe-88fw-Jfuhji_W0rtg = jose4j_encrypt: serializedJwe

可以看到,最终结果中的"alg“标题是”ECDH“,而不是所需的"dir”。

如果我要实现双方的沟通,那就足够了,但是有了这个规范,这里似乎缺少了许多配置.

使用jose4j的代码更长,而且看起来更可配置,但我无法构造足够有价值的东西在这里发布。

对于我来说,缺少的主要部分是如何从上面的规范中生成CEK。

谢谢。

编辑

在上面添加了jose4j代码并添加了输出.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-12 14:55:40

下面是一些使用jose4j的示例代码,我认为这些代码可以满足您的需要。您所指向的示例类似于JWE的明文是JWS/JWT,但它可以是任意的内容。CEK生成/派生的细节由底层的JWE功能处理。请注意,这只加密内容,不提供完整性保护或发送者身份验证。

代码语言:javascript
复制
    String encodedCert = "MIIBRjCB7KADAgECAgYBaqxRCjswDAYIKoZIzj0EAwIFADApMQswCQYDVQQGEwJDQTEMMAoGA1UE\n" +
            "ChMDbWVoMQwwCgYDVQQDEwNtZWgwHhcNMTkwNTEyMTM1MjMzWhcNMjAwNTExMTM1MjMzWjApMQsw\n" +
            "CQYDVQQGEwJDQTEMMAoGA1UEChMDbWVoMQwwCgYDVQQDEwNtZWgwWTATBgcqhkjOPQIBBggqhkjO\n" +
            "PQMBBwNCAAQH83AhYHCehKj7M5+UTNshwLFqqqJWGrJPNj9Kr7xvxtcZnyjq+AKLGMLfdk/G7yb8\n" +
            "4vIh0cJwtVs70WgIXT8xMAwGCCqGSM49BAMCBQADRwAwRAIgO0PJRzan2msHpcvcqhybzeualDea\n" +
            "/X2QGAWCYT+sNiwCIDMrfhrzUQ6uIX4vnB8AYqb85Ssl7Qcl9nYtjHb08NR8";

    X509Util x509Util = new X509Util();
    X509Certificate x509Certificate = x509Util.fromBase64Der(encodedCert);

    // the JWE object
    JsonWebEncryption jwe = new JsonWebEncryption();

    // The output of the ECDH-ES key agreement will be used as the content encryption key
    jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES);

    // The content encryption key is used to encrypt the payload
    // with a composite AES-CBC / HMAC SHA2 encryption algorithm
    jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);

    // don't think you really need this but you had ""apv":DirectoryServerID" in the question so...
    jwe.setHeader(HeaderParameterNames.AGREEMENT_PARTY_V_INFO, Base64Url.encodeUtf8ByteRepresentation("<<DirectoryServerID>>"));

    // We encrypt to the receiver using their public key
    jwe.setKey(x509Certificate.getPublicKey());

    // and maybe put x5t to help the receiver know which key to use in decryption
    jwe.setX509CertSha1ThumbprintHeaderValue(x509Certificate);

    // What is going to be encrypted
    jwe.setPayload("Your text here. It can be JSON or whatever.");

    // Produce the JWE compact serialization, which is a string consisting of five dot ('.') separated
    // base64url-encoded parts in the form Header..IV.Ciphertext.AuthenticationTag
    String serializedJwe = jwe.getCompactSerialization();

    System.out.println(serializedJwe);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56096907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档