Skip to content

Commit

Permalink
Fix compression being omitted for JWEs with arbitrary content
Browse files Browse the repository at this point in the history
The JWE content was compressed only when claims was used as payload, but
when using arbitrary content, the compression was omitted, while keeping
the "zip" header field, leading to decompression failing.
  • Loading branch information
mnylen committed Apr 22, 2024
1 parent c673b76 commit 700a92a
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 3 deletions.
Expand Up @@ -693,14 +693,14 @@ private String encrypt(final Payload content, final Key key, final Provider keyP
Assert.stateNotNull(keyAlgFunction, "KeyAlgorithm function cannot be null.");
assertPayloadEncoding("JWE");

ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
InputStream plaintext;
if (content.isClaims()) {
ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
writeAndClose("JWE Claims", content, out);
plaintext = Streams.of(out.toByteArray());
} else {
plaintext = content.toInputStream();
writeAndClose("JWE Content", content, out);
}
plaintext = Streams.of(out.toByteArray());

//only expose (mutable) JweHeader functionality to KeyAlgorithm instances, not the full headerBuilder
// (which exposes this JwtBuilder and shouldn't be referenced by KeyAlgorithms):
Expand Down
92 changes: 92 additions & 0 deletions impl/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy
Expand Up @@ -22,6 +22,7 @@ import io.jsonwebtoken.impl.io.Streams
import io.jsonwebtoken.impl.lang.Bytes
import io.jsonwebtoken.impl.lang.Services
import io.jsonwebtoken.impl.security.*
import io.jsonwebtoken.io.CompressionAlgorithm
import io.jsonwebtoken.io.Decoders
import io.jsonwebtoken.io.Deserializer
import io.jsonwebtoken.io.Encoders
Expand Down Expand Up @@ -1398,6 +1399,97 @@ class JwtsTest {
}
}

@Test
void testJweCompressionWithArbitraryContentString() {
def codecs = [Jwts.ZIP.DEF, Jwts.ZIP.GZIP]

for (CompressionAlgorithm zip : codecs) {

for (AeadAlgorithm enc : Jwts.ENC.get().values()) {

SecretKey key = enc.key().build()

String payload = 'hello, world!'

// encrypt and compress:
String jwe = Jwts.builder()
.content(payload)
.compressWith(zip)
.encryptWith(key, enc)
.compact()

//decompress and decrypt:
def jwt = Jwts.parser()
.decryptWith(key)
.build()
.parseEncryptedContent(jwe)
assertEquals payload, new String(jwt.getPayload(), StandardCharsets.UTF_8)
}
}
}

@Test
void testJweCompressionWithArbitraryContentByteArray() {
def codecs = [Jwts.ZIP.DEF, Jwts.ZIP.GZIP]

for (CompressionAlgorithm zip : codecs) {

for (AeadAlgorithm enc : Jwts.ENC.get().values()) {

SecretKey key = enc.key().build()

byte[] payload = new byte[14];
Randoms.secureRandom().nextBytes(payload)

// encrypt and compress:
String jwe = Jwts.builder()
.content(payload)
.compressWith(zip)
.encryptWith(key, enc)
.compact()

//decompress and decrypt:
def jwt = Jwts.parser()
.decryptWith(key)
.build()
.parseEncryptedContent(jwe)
assertArrayEquals payload, jwt.getPayload()
}
}
}

@Test
void testJweCompressionWithArbitraryContentInputStream() {
def codecs = [Jwts.ZIP.DEF, Jwts.ZIP.GZIP]

for (CompressionAlgorithm zip : codecs) {

for (AeadAlgorithm enc : Jwts.ENC.get().values()) {

SecretKey key = enc.key().build()

byte[] payloadBytes = new byte[14];
Randoms.secureRandom().nextBytes(payloadBytes)

ByteArrayInputStream payload = new ByteArrayInputStream(payloadBytes)

// encrypt and compress:
String jwe = Jwts.builder()
.content(payload)
.compressWith(zip)
.encryptWith(key, enc)
.compact()

//decompress and decrypt:
def jwt = Jwts.parser()
.decryptWith(key)
.build()
.parseEncryptedContent(jwe)
assertArrayEquals payloadBytes, jwt.getPayload()
}
}
}

@Test
void testPasswordJwes() {

Expand Down

0 comments on commit 700a92a

Please sign in to comment.