首页 > 解决方案 > iOS JWE AES GCM 256

问题描述

我正在尝试使用 JOSESwift(修改为支持 AES-GCM 256)和 CryptoSwift(需要支持 iOS 11+)在 Swift 中实现 JWE 令牌。我能够使用公钥/私钥对进行加密和解密。但是,当相同的 JWE 令牌传递给 Java(服务器端程序)时,它无法解密。反之亦然也不起作用。需要帮助,可以分享我的github项目

https://github.com/sreekanthps/VAMDemoJava.git - Java 项目https://github.com/sreekanthps/VMADemo.git - iOS 项目https://github.com/sreekanthps/JOSESwift-AES256GCM.git - 修改后的 JOSESwift项目

雨云

线程“主”com.nimbusds.jose.JOSEException 中的异常:AES/GCM/NoPadding 解密失败:标签不匹配!在 com.nimbusds.jose.crypto.impl.AESGCM.decrypt(AESGCM.java:301) 在 com.nimbusds.jose.crypto.impl.ContentCryptoProvider.decrypt(ContentCryptoProvider.java:279) 在 com.nimbusds.jose.crypto .RSADecrypter.decrypt(RSADecrypter.java:285) 在 com.nimbusds.jose.JWEObject.decrypt(JWEObject.java:415) 在 me.txedo.security.Main.numbusJWe(Main.java:127) 在 me.txedo。安全.Main.main(Main.java:52)

何塞4j

线程“主”org.jose4j.lang.JoseException 中的异常:javax.crypto.AEADBadTagException:标签不匹配!在 org.jose4j.jwe.SimpleAeadCipher.decrypt(SimpleAeadCipher.java:114) 在 org.jose4j.jwe.SimpleAeadCipher.decrypt(SimpleAeadCipher.java:101) 在 org.jose4j.jwe.AesGcmContentEncryptionAlgorithm.decrypt(AesGcmContentEncryptionAlgorithm.java:79) ) 在 org.jose4j.jwe.JsonWebEncryption.decrypt(JsonWebEncryption.java:249) 在 org.jose4j.jwe.JsonWebEncryption.getPlaintextBytes(JsonWebEncryption.java:85) 在 org.jose4j.jwe.JsonWebEncryption.getPlaintextString(JsonWebEncryption.java: 78) 在 org.jose4j.jwe.JsonWebEncryption.getPayload(JsonWebEncryption.java:93) 在 me.txedo.security.Main.jose4JDeryption(Main.java:166) 在 me.txedo.security.Main.main(Main.java :55)

SWIFT代码

keyData =  try! randomData(ofLength: 32)
        ivData = try! randomData(ofLength: 16)
        let message = "Summer ⛱, Sun ☀️, Cactus ".data(using: .utf8)!
        let header = JWEHeader(keyManagementAlgorithm: .RSAOAEP256, contentEncryptionAlgorithm: .AES256GCM)
        let payload = Payload(message)
        let publickey =  RSAKeyGenerator.shared.getPublicKey()
        let privateKey = RSAKeyGenerator.shared.getPrivateKey()
        let encrypter = Encrypter(keyManagementAlgorithm: .RSAOAEP256, contentEncryptionAlgorithm: .AES256GCM, encryptionKey: publickey!)!
        if let jwe = try? JWE(header: header, payload: payload, encrypter: encrypter) {
            jwtString = jwe.compactSerializedString
            print("jwtString : \(jwtString!)")
        }
        do {
            let jwe = try JWE(compactSerialization: jwtString!)
            let decrypter = Decrypter(keyManagementAlgorithm: .RSAOAEP256, contentEncryptionAlgorithm: .AES256GCM, decryptionKey: privateKey!)!
            let payload = try jwe.decrypt(using: decrypter)
            let message = String(data: payload.data(), encoding: .utf8)!
            print(message) // Summer ⛱, Sun ☀️, Cactus 
        }catch {
            print("Decryption error :\(error.localizedDescription)")
        }

Java 代码

protected final static Logger LOGGER = Logger.getLogger(Main.class);
    
    public final static String RESOURCES_DIR = "/Users/swesree/Desktop/KH802/CERTS/";

    public static void main(String[] args) throws FileNotFoundException,
            IOException, NoSuchAlgorithmException, NoSuchProviderException, ParseException, JOSEException, JoseException {
        Security.addProvider(new BouncyCastleProvider());
        LOGGER.info("BouncyCastle provider added.");

        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");

        try {
            PrivateKey priv = generatePrivateKey(factory, RESOURCES_DIR + "vmaprivate.pem");
            
            LOGGER.info(String.format("Instantiated private key: %s", priv));
            
            PublicKey pub = generatePublicKey(factory, RESOURCES_DIR + "vmapublic.pem");
            LOGGER.info(String.format("Instantiated public key: %s", pub));
            //numbusJWe(pub,priv);
            
            String jweString = jose4JEcnryption(pub);
            jose4JDeryption(priv,jweString);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
    }

    private static PrivateKey generatePrivateKey(KeyFactory factory, String filename)
            throws InvalidKeySpecException, FileNotFoundException, IOException {
        PemFile pemFile = new PemFile(filename);
        byte[] content = pemFile.getPemObject().getContent();
        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
        return factory.generatePrivate(privKeySpec);
    }
    
    private static PublicKey generatePublicKey(KeyFactory factory, String filename)
            throws InvalidKeySpecException, FileNotFoundException, IOException {
        PemFile pemFile = new PemFile(filename);
        byte[] content = pemFile.getPemObject().getContent();
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
        return factory.generatePublic(pubKeySpec);
    }
    
    private static void numbusJWe(PublicKey publicKey, PrivateKey privKey) throws ParseException, JOSEException {
        Date now = new Date();
        
        JWTClaimsSet jwtClaims = new JWTClaimsSet.Builder()
                    .issuer("https://openid.net")
                    .subject("alice")
                    .audience(Arrays.asList("https://app-one.com", "https://app-two.com"))
                    .expirationTime(new Date(now.getTime() + 1000*60*10)) // expires in 10 minutes
                    .notBeforeTime(now)
                    .issueTime(now)
                    .jwtID(UUID.randomUUID().toString())
                    .build();
            System.out.println(jwtClaims.toJSONObject());
            // Request JWT encrypted with RSA-OAEP-256 and 128-bit AES/GCM
            JWEHeader header = new JWEHeader(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM);
                // Create the encrypted JWT object
            EncryptedJWT jwt = new EncryptedJWT(header, jwtClaims);
            // Create an encrypter with the specified public RSA key
            RSAEncrypter encrypter = new RSAEncrypter((RSAPublicKey) publicKey);
            // Do the actual encryption
            jwt.encrypt(encrypter);
            // Serialise to JWT compact form
            String jwtString = jwt.serialize();
            System.out.println("jwtString : "+jwtString);
                
        //
        //
            // Parse back
            //String jwtStringNew = "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.hJ905rCCsW0u07cCleTh_eYKAyDP7ZHNnRA50qDWXo7seygePzIkr37ZCeaW2hmZ-c6v_c7Yp3Y0kzE5OE0h93J09XAtYfwZk3zZVKXH8hd6fWjeY7ZgB8I4CpQaa9BX-Zp9bBznXHh5WqpckkMAXZVT-wiLNVqQDpyg8Jifi5tuw4SjT4irRrFYF5LfSDLU4EigKKC3Rn1IOlwEKhHuvqLFuCbqgXVh_Ps75P9_wXr3XoKSwEDf5zbOh42cPlenKfG0TQpeEhKamEbmpuRnOZYRHmOQ0d6KTI7t8xxRQ0g3nF0AJGQKwnbZDgZPli8v3dI8XZY9rca03rG8aQpCag.JFWISQTeuw2euVfT.5ekMlQk5tkPFLdUnZIh-GMfFGS36UPKAd_obtu-YCy_vv_iuNPVbxZyzjJFRnK2-G8Cf3UuKvpNusyjpd_AfIvoxg7fqCr95CZ8IulBGo1SddvcXx-kCsCNPawK97pN7qclHc6oqrIpK4CjUR0msJtgNbdTrFI0VOw1dLXoz_jFJ13xO1LQiXkxdJltD6qpEfE3x1UyNFpDHudplur7v6cd9WOXNFlQ6zQYfn-9ZHOMGoGFcQAB9u9crCkoyIX4vifNrJA.zD8126ElxZvp-RODUr5qSg";
            String jwtStringNew =  "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.wDiB-oEawb6cBHUyHT-_LVtRwaA7bwL8qwoqXGYayXae6EFr6wKIP2M5woq9HSGWRFH48JIyNS6V_K3MdXfh9oqjVd3djBeUKtcP6b-2jWjFxLL-WOgZpHmSMpWhOB55ogKQRumo0YYn4HMd8JrQ48uYGa7NoWOxMIBajKNu4utkOW-1q-ccbN4_6mds90brEJDnlbcHyo22sjufiXeKhN8_JaN6uqx3qet08ouhEEOaFhssj7nyP3ynz75rT17iw_VAoS91JP6lb-Q4T4ZsA_9_ibZUZn4vkk1mWU0Kul2Hp0z5GXw_ZPNi7IsTv0D4xvDnWmwTUb3ekdj0cCYmMg.e0w_dONIFxka8bXU.bEAl8JYqj-4xSlC1i4xXSbdMqBz61TuKUHdYq46L2_vxTpTjh04o5juH4eDbs6cfEgGy.44dOKOY7h-Hg27OnHxIBsg";
            EncryptedJWT jwt1= EncryptedJWT.parse(jwtStringNew);
        
            // Create a decrypter with the specified private RSA key
            RSADecrypter decrypter = new RSADecrypter(privKey);
        
            // Decrypt
            jwt1.decrypt(decrypter);
        
                
            System.out.println(jwt1.getHeader());
            System.out.println("numbusJWe::: "+jwt1.getPayload());
// TODO Auto-generated method stub
    }
    
    private static String  jose4JEcnryption(PublicKey key) throws JoseException {
        JsonWebEncryption jwe = new JsonWebEncryption();
         jwe.setPayload("Hello World!");
         jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.RSA_OAEP_256);
         jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM);
         jwe.setKey(key);
         String serializedJwe = jwe.getCompactSerialization();
         System.out.println("Serialized Encrypted JWE: " + serializedJwe);
         return serializedJwe;
    }
    
    private static void  jose4JDeryption(PrivateKey key, String jweToken) throws JoseException {
        String jwtStringNew1 = "eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.wDiB-oEawb6cBHUyHT-_LVtRwaA7bwL8qwoqXGYayXae6EFr6wKIP2M5woq9HSGWRFH48JIyNS6V_K3MdXfh9oqjVd3djBeUKtcP6b-2jWjFxLL-WOgZpHmSMpWhOB55ogKQRumo0YYn4HMd8JrQ48uYGa7NoWOxMIBajKNu4utkOW-1q-ccbN4_6mds90brEJDnlbcHyo22sjufiXeKhN8_JaN6uqx3qet08ouhEEOaFhssj7nyP3ynz75rT17iw_VAoS91JP6lb-Q4T4ZsA_9_ibZUZn4vkk1mWU0Kul2Hp0z5GXw_ZPNi7IsTv0D4xvDnWmwTUb3ekdj0cCYmMg.e0w_dONIFxka8bXU.bEAl8JYqj-4xSlC1i4xXSbdMqBz61TuKUHdYq46L2_vxTpTjh04o5juH4eDbs6cfEgGy.44dOKOY7h-Hg27OnHxIBsg";
        JsonWebEncryption jwe = new JsonWebEncryption();
        jwe.setAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.PERMIT, 
                KeyManagementAlgorithmIdentifiers.RSA_OAEP_256));
         jwe.setContentEncryptionAlgorithmConstraints(new AlgorithmConstraints(ConstraintType.PERMIT, 
                ContentEncryptionAlgorithmIdentifiers.AES_256_GCM));
         jwe.setKey(key);
         jwe.setCompactSerialization(jwtStringNew1);
         System.out.println("JOSE4J ::: getHeaders :::: " + jwe.getHeaders());
         System.out.println("JOSE4J ::: getContentEncryptionAlgorithm :::: " + jwe.getContentEncryptionAlgorithm());
         System.out.println("JOSE4J ::: getEncryptedKey :::: " + jwe.getEncryptedKey());
         System.out.println("JOSE4J ::: getIv :::: " + jwe.getIv());
         System.out.println("JOSE4J ::: Payload :::: " + jwe.getPayload());
    }

标签: swiftcryptoswiftjose4jnimbus-jose-jwt

解决方案


推荐阅读