我正在尝试使用 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());
}