Skip to content

Commit

Permalink
Add additional copy to explain the padding that we may encounter when…
Browse files Browse the repository at this point in the history
… extracting the r and s components, and how the result must be padded to correctly fill the result.
  • Loading branch information
robotdan committed Feb 29, 2024
1 parent af79d25 commit 0cff1e0
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/main/java/io/fusionauth/jwt/ec/ECDSASignature.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public byte[] derDecode(Algorithm algorithm) throws IOException {
byte[] r = sequence[0].getPositiveBigInteger().toByteArray();
byte[] s = sequence[1].getPositiveBigInteger().toByteArray();

// The length of the result is fixed and discrete per algorithm.
byte[] result;
switch (algorithm) {
case ES256:
Expand All @@ -85,8 +86,26 @@ public byte[] derDecode(Algorithm algorithm) throws IOException {
throw new IllegalArgumentException("Unable to decode the signature for algorithm [" + algorithm.name() + "]");
}

// Because the response is not encoded, the r and s component must take up an equal amount of the resulting array.
// This allows the consumer of this value to always safely split the value in half based upon an index value since
// the result is not encoded and does not contain any meta-data about the contents.
int len = result.length / 2;

// The extracted byte array of the DER encoded value can be left padded. For this reason, the component lengths
// may be greater than 'len' which is half of the result. So for example, if r is left padded, the length may be
// equal to 67 in ES512 even though len is only 66. This is why we must calculate the source position for reading
// when we copy the r byte array into the result. The same is potentially true for either component. We cannot
// make an assumption that the source position in r or s will be 0.
//
// Similarly, when the r and s components are not padded, but they are shorter than len, we need to pad the value
// to be right aligned in the result. This is why the destination position may not be 0 or len respectively for
// r and s.
//
// If s is 65 bytes, then the destination position in the 0 initialized resulting array needs to be len + 1 so that
// we write the final byte of s at the end of the result.
//
// For clarity, calculate each input to the arraycopy method first.

int rSrcPos = r.length > len ? (r.length - len) : 0;
int rDstPos = Math.max(0, len - r.length);
int rLength = Math.min(r.length, len);
Expand Down

0 comments on commit 0cff1e0

Please sign in to comment.