Java密码学中'AGCM256-KW'的算法字符串是什么,用于Cipher.getInstance(String algo)?



引用此信息,我必须使用算法 AGCM256-KW 加密。我正在使用Java密码学,但没有找到任何这样的算法。我发现最接近的是 AES_256/gcm/nopadding ,但没有KW(密钥包装)。

这是我的测试代码

    public void testEncryption(String algo) {
    String shared_secret = "LyQnklSrxsk3Ch2+AHi9HoDW@//x1LwM123QP/ln";
    try {
        // Step 1 - Create SHA-256 digest of the shared key
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] digest = md.digest(shared_secret.getBytes("UTF-8"));
        // Step 2 - generate a 256 bit Content Encryption Key(CEK)
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        kg.init(256);
        SecretKey cek = kg.generateKey();
        // Step 3 - encrypt the CEK using 256 bit digest generated in Step 1
        // and 96 bit random IV. Algorithm should be
        // random 96 bit Initialize Vector
        SecureRandom random = new SecureRandom();
        // byte iv[] = new byte[96];
        // random.nextBytes(iv);
        byte iv[] = random.generateSeed(96);
        System.out.println("IV: " + toBase64(iv) + " length: " + iv.length);
        IvParameterSpec ivspec = new IvParameterSpec(iv);
        GCMParameterSpec gspec = new GCMParameterSpec(96, iv);
        // encrypt
        Cipher cipher = Cipher.getInstance(algo);
        System.out.println(String.format("CEK Cipher alg:%S provider:%S", cipher.getAlgorithm(),
                cipher.getProvider().getName()));
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(digest, "AES"), gspec);
        byte[] result = cipher.doFinal(cek.getEncoded());
        System.out.println(String.format("Encrypted CEK :%S", toBase64(result)));
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

更新1 我想我可以使用具有JWE的API的Jose4j库。

是的,Visa令牌服务似乎正在使用JWE(现在RFC 7516),因此您可以使用Jose4j。这是一些示例代码,显示使用A256GCMKW和AGCM256加密和解密JWE的某些内容:

    // shared secret hashed to key from your example
    String shared_secret = "LyQnklSrxsk3Ch2+AHi9HoDW@//x1LwM123QP/ln";
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    byte[] digest = md.digest(shared_secret.getBytes("UTF-8"));
    JsonWebEncryption jwe = new JsonWebEncryption();
    // A256GCMKW for key wrap
    jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.A256GCMKW);
    // A256GCM for content encryption
    jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM);
    // the key (from above)
    jwe.setKey(new SecretKeySpec(digest, "AES"));
    // whatever content you want to encrypt
    jwe.setPayload("some important content to be encrypted and integrity protected");
    // Produce the JWE compact serialization, which is where the actual encryption is done.
    // The JWE compact serialization consists of five base64url encoded parts
    // combined with a dot ('.') character in the general format of
    // <header>.<encrypted key>.<initialization vector>.<ciphertext>.<authentication tag>
    String serializedJwe = jwe.getCompactSerialization();

    // Do something with the JWE. Like send it to some other party over the clouds
    // and through the interwebs.
    System.out.println("JWE compact serialization: " + serializedJwe);
    // That other party, the receiver, can then use JsonWebEncryption to decrypt the message.
    JsonWebEncryption receiverJwe = new JsonWebEncryption();
    // Set the compact serialization on new Json Web Encryption object
    receiverJwe.setCompactSerialization(serializedJwe);
    // Symmetric encryption, like we are doing here, requires that both parties have the same key.
    // The key will have had to have been securely exchanged out-of-band somehow.
    receiverJwe.setKey(new SecretKeySpec(digest, "AES"));
    // Get the message that was encrypted in the JWE. This step performs the actual decryption steps.
    String plaintext = receiverJwe.getPlaintextString();
    // And do whatever you need to do with the clear text message.
    System.out.println("plaintext: " + plaintext);

让我们假设您确实需要在GCM模式下AES(我从未听说过AGCM,但我想这是一个合乎逻辑的假设,即表示AES/GCM)。然后,以下内容可用于(联合国)包装秘密键。请注意,我没有使用IvParameterSpec来工作,至少没有用于Oracle JCE。

SecretKey sk = new SecretKeySpec(new byte[16], "AES");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, new byte[12]);
cipher.init(Cipher.WRAP_MODE, sk, gcmSpec);
byte[] wrappedKey = cipher.wrap(sk);
System.out.println(Hex.toHexString(wrappedKey));
cipher.init(Cipher.UNWRAP_MODE, sk, gcmSpec);
SecretKey unwrap = (SecretKey) cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
System.out.println(Hex.toHexString(unwrap.getEncoded()));

请注意,使用SIV模式可能是包装密钥的首选,因为您不需要将IV 身份验证标签与包装键一起存储(存储IV中未显示IV)例子)。上面的代码依赖于唯一的iv安全性(也未显示)。

显然,用自己包裹钥匙也不是一个好主意。抱歉,我在这里有些懒惰。我刚刚显示了如何使用密码。

" kw"是指RFC 3394中定义的"密钥包装"。JCE中此算法的名称是" aeswrap"。因此,转换应为" aeswrap/gcm/nopadding"。正如Maarten指出的那样,从逻辑上讲,此操作应在WRAP_MODE中配置Cipher

最新更新