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

ECDH JWE使用jose4j加密/解密

太叔坚
2023-03-14

我试图在Android(Java)中实现ECDH加密/解密和JWE。
我找到了jose4j和Nimbus JOSE库,它们旨在做我需要的一切,但似乎比我想象的更具挑战性。

如果有人熟悉的话,那就是3D安全2.0。。。

在以下规范中:

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

接下来是规范:

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

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

    在jose4j的示例中有一个使用ECDH创建JWT的示例:
    https://bitbucket.org/b_c/jose4j/wiki/JWT示例(最后一个示例,标题为“生成和使用html" target="_blank">嵌套(签名和加密)JWT”)<但是这个例子并不是我所需要的。当我需要加密文本时,它会创建一个令牌。

    从上述规范中的“CEK:kty:oct-256比特”开始,我不知道该怎么做。

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

    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_encrypt:jwe={“epk”:{“kty”:“EC”,“crv”:“P-256”,“x”:“AS0GRFAOWIDONXAPR”4IuNHcDIUJPHbACjG5L7x-nQ”,“y”:“XONFN1 VRASKUTCKFTWSL16LRMSE-bAF8EO4-mh1NYw”;“apv”:“RJAWMDAWMQ”,“enc”:“A128CBC-HS256”,“alg”:“ECDH-ES”}

    nimbus_encrypt:serializedJwe=EYJLCGSIONSIA3R5IjOijUijUiqlti1NiisingioijBuzbuzbumzbt1djre9OwhhhufJfnel1Td1Td4Lw5Riiwiesi6inVbkZumxzzzQVnLvLvKqTgVhdZbde2Td2Tf2UtyKfGoeVvPc1AdfowxIf2IjIjIjFb0ExIjIjUf0EqLf3IjIjIjIjIjIjIjIjIjIjIjIjIjIjIjIjIj。。Pi48b7uj3UilvVXKewFacg。0sx9OkHxxtZvkVm IENRFw。BU5GVOAWCZDXDKWIBKWA

    这是我使用jose4j lib的代码(到目前为止,使用@Brian-Campbell的答案):

    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输出:

    jose4j_encrypt: jwe=JsonWebEncryption{"alg":"ECDH-ES","enc":"A128CBC-HS256","apv":"RjAwMDAwMDAwMQ","epk":{"kty":"EC","x":"prvyhexJXDWvPQmPA1xBjY8mkHEbrEiJ4Dr-7_5YfdQ","y":"fPjw8UdfzgkVTppPSN5o_wprItKLwecoia9yrWi38yo","crv":"P-256"}}

    jose4j_encrypt:serializedJwe=EYJHBGCIOIJFQ0riluvTiiWizW5jijoiqyIuisMfWdII6ILJQxDnRef3Turbd01riIwizBrij7imt0esikVdIIWIECI6inbydnlozxKwerxDlbbBmbmXhcalk4bWyrlWlWllKnylTfNvLmZfeilcJ5IjoizLbQdHvZgZZZZ2TwWwWwWbWfNonW9Fd3Fd2YLd2YLdJ9Fd2YLd2YLdJ9Fd2YLdLd2YLdLd2YL。。gxWYwFQSOqLk5HAgs7acdA。mUIHBiWpWSlQaEOJ_EZGYA。eiTe-88fw-Jfuhji_W0rtg

    可以看出,最终结果中的"alg"报头是"ECDH-ES"而不是"dir"。

    如果我将实现html" target="_blank">通信的双方,那么就足够了,但是有了这个规范,似乎这里缺少了许多配置...

    使用jose4j的代码更长,看起来更具可配置性,但我无法构建一些有价值的东西来发布在这里。

    我缺少的主要部分是如何从上面的规范生成CEK。

    非常感谢。

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

共有1个答案

田博超
2023-03-14

下面是一些使用jose4j的示例代码,我认为它可以实现您正在寻找的功能。您所指出的示例与JWE的纯文本类似,即JWS/JWT,但它可以是任意内容。CEK生成/派生的细节由底层JWE功能处理。请注意,这仅对内容进行加密,不提供完整性保护或发件人身份验证。

    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);
 类似资料:
  • 我需要在iPhone或iPad上加密字符串(实际上是XML文件),然后用.NET应用程序解密。感谢David Veksler在这里提出的问题“.NET和iPhone之间的AES互操作性?”,以及在这里发表的博客文章http://automagical.rationalmind.net/2009/02/12/aes-interoperability-between-net-and-iPhone/。

  • 我正在尝试使用KMS和AWS加密SDK加密数据。查看AWS文档中提供的示例,似乎没有地方可以显式设置数据键。 使用由KMS生成的数据密钥使用AWS加密SDK加密数据的推荐方法是什么?

  • 问题内容: 有没有一种方法可以解密Java中的密码。Java将算法实现为。我得到了创建密码哈希的代码。我在下面提到了哈希技术的链接: http://howtodoinjava.com/security/how-to-generate-secure-password-hash- md5-sha-pbkdf2-bcrypt-examples/ 我的要求是以加密格式存储第三方FTP服务器密码,并在需要登

  • 问题内容: 有人要求我用PHP解密使用以下Java类加密的字符串。 我不懂Java,因此我需要一些帮助来理解这种加密。 1)这行是什么意思? 2)我应该为第一个参数使用什么值 3)什么时候应该在我的php脚本中使用MD5? 问题答案: 1)它创建用于基于密码的加密的参数,哈希计算中包含的盐和哈希算法执行的迭代次数(在其自身的输出中)。它用于击退彩虹表攻击,基本上,攻击者必须经过相同的迭代次数才能检

  • 问题内容: 下面的加密功能似乎起作用,因为它似乎可以加密文件并将其放置在预期的目录中。我现在正在尝试解密文件,并且它只死于消息“无法完成解密”(在此处进行编码…)。php错误日志中没有任何内容,因此我不确定为什么它会失败,但由于mcrypt对我来说是全新的,所以我更倾向于相信自己在这里做错了… 功能如下: 问题答案: 由于mcrypt是一种废弃软件,不再建议使用,因此这里是使用openssl的示例

  • 我使用的是Web加密,更具体地说,这些示例是:https://github.com/diafygi/webcrypto-examples/#rsa-oaep 更新