I am trying to raw deflate the JSON string in Java using Deflater.class. But there is some difference between the deflated results generated by java and typescript.
let bodyString = JSON.stringify(idTokenPayload);
const fields = deflate ? { zip: 'DEF' } : {};
const body = deflate ? pako.deflateRaw(bodyString) : bodyString;
In Java,
protected String deflateAndBase64Encode(String jsonString) {
try {
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, true);
DeflaterOutputStream deflaterStream = new DeflaterOutputStream(bytesOut, deflater);
deflaterStream.write(jsonString.getBytes());
deflaterStream.finish();
return Base64.getEncoder().encodeToString(bytesOut.toByteArray());
} catch (IOException e) {
}
return "";
}
Update:
I need to convert the JSON payload as below to generate the smart health card. Json Payload -> Minified JSON - > Raw deflate -> JWS sign using ES256 alg Currently, the examples are available only in javascript which is working fine. But whatever generated in the java application is failing at the verifier applications.
async signJws(idTokenPayload: Record<string, unknown>, deflate = true): Promise<string> {
let bodyString = JSON.stringify(idTokenPayload);
const fields = deflate ? { zip: 'DEF' } : {};
const body = deflate ? pako.deflateRaw(bodyString) : bodyString;
let b64 = Buffer.from(body).toString('base64');
const signed = await jose.JWS.createSign({ format: 'compact', fields }, this.signingKey)
.update(Buffer.from(body))
.final();
return (signed as unknown) as string;
}
}
In Java,
private String signPayload(String deflatedString, int index) {
JwsHeaders jsHeaders = new JwsHeaders(SignatureAlgorithm.ES256);
InputStream is = getClass().getClassLoader().getResourceAsStream("issuer.jwks.private.json");
JsonWebKeys keySet;
try {
keySet = JwkUtils.readJwkSet(is);
JsonWebKey key = keySet.getKeys().get(index);
jsHeaders.setProperty("zip", "DEF");
jsHeaders.setProperty("kid", key.getKeyId());
JwsCompactProducer jwsJsonProducer = new JwsCompactProducer(jsHeaders, deflatedString);
String signed = jwsJsonProducer.signWith(key);
return signed;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
This is generally working-as-intended.
There are many deflated byte strings that inflate back to the same output. There's no particular obligation for two deflaters to produce the same output. You're demonstrating that yourself, to some extent, by configuring the Java deflation for BEST_COMPRESSION
.