| 372 | // ECDSA signatures: platform sign() returns ASN.1 DER (SEQUENCE { r, s }), |
| 373 | // JWT requires raw r||s. Tiny converters here keep ES* support compact. |
| 374 | private static byte[] derToJoseEcdsa(byte[] der, int coordLen) { |
| 375 | // SEQUENCE (0x30) length ... |
| 376 | // INTEGER (0x02) lenR rBytes |
| 377 | // INTEGER (0x02) lenS sBytes |
| 378 | if (der.length < 8 || (der[0] & 0xff) != 0x30) { |
| 379 | throw new CryptoException("bad ECDSA DER signature"); |
| 380 | } |
| 381 | int p = 2; |
| 382 | if ((der[1] & 0x80) != 0) { |
| 383 | int n = der[1] & 0x7f; |
| 384 | p = 2 + n; |
| 385 | } |
| 386 | if ((der[p] & 0xff) != 0x02) { |
| 387 | throw new CryptoException("bad ECDSA DER signature"); |
| 388 | } |
| 389 | int rLen = der[p + 1] & 0xff; |
| 390 | int rOff = p + 2; |
| 391 | int sStart = rOff + rLen; |
| 392 | if ((der[sStart] & 0xff) != 0x02) { |
| 393 | throw new CryptoException("bad ECDSA DER signature"); |
| 394 | } |
| 395 | int sLen = der[sStart + 1] & 0xff; |
| 396 | int sOff = sStart + 2; |
| 397 | byte[] out = new byte[coordLen * 2]; |
| 398 | copyAndPad(der, rOff, rLen, out, 0, coordLen); |
| 399 | copyAndPad(der, sOff, sLen, out, coordLen, coordLen); |
| 400 | return out; |
| 401 | } |
| 402 | |
| 403 | private static void copyAndPad(byte[] src, int srcOff, int srcLen, |
| 404 | byte[] dst, int dstOff, int dstLen) { |