PeculiarVentures / PKI.js

PKI.js is a pure JavaScript library implementing the formats that are used in PKI applications (signing, encryption, certificate requests, OCSP and TSP requests/responses). It is built on WebCrypto (Web Cryptography API) and requires no plug-ins.
http://pkijs.org
Other
1.25k stars 204 forks source link

Cannot round-trip RSA public key that is not a power of 2 to/from JWK #389

Open achingbrain opened 5 months ago

achingbrain commented 5 months ago

I'm trying to port a module from node-forge to PKIjs but have come across a problem.

Given the following 8200 bit RSA public key represented as JWK:

{
  "kty": "RSA",
  "n": "AtSHgbWZ-5MHNh8LpVD4-2lOjLitwGjADZ8gEcs3EqskGl1E7Lna8oGRt6V-0yiGwicgNgWPVRW3M4aK8kXe9izb1O43I20A2QVfmZDZB7inS23hrj9PZs863x497-WMdiyBBa3SVrg0StU_vQ8iUFYi5ihQr0b58IKJhVHA6AhqpuUeCbbTakoH1btzOlfqWb6chlL2bT-1KY1EUSRN25Qrfk5T7wV59QvbkGMUuHJRreh6caTASf3cGEG6nk_2YXTiZ6Yyc5XzR0hNervbwa9WVPc19iCP9fNJ8T6oFmJsJ-T9MnEQqttDSOYGwhnzleV4FWrv0jiWhC1-LMdJ-rdHVXPUH9pKArXwWu1FZBk8EG4o3uAB5rcxgk7Z_5sV3PAXQlAISZl3IwauWcDaWIgckDUU3AmzpdrddPn8IiqVtSpcTMISi2MkKJw1iom97iQk8V0dkPvCpFB1wzOoEJfL-gcl61ePeU5xohzy0eQcwjsGAtuK6XgT_TB_u7Q6_FbS0AwySISYz6JsnV-FHsb-0FMUjj6-jF0A3vb7El43xwZUrAhx7qqn_DuvrztjChsNWyE7dKWDceTwxIHDobEG7LDivMvsq-jkRYIzYoMJabrIzTgRjGBLruxBp8Zl1CuOepD4vFO6JBzbZl5Qy0hrpuP9YAlYBg3sBhwsYcrATZWVYcNRkJDsNIo-lSFNOl8DalFm7IsxW0A6AMuysLzm4oLZe2hDrmfRI9Mh5JBgio8cKetZan-0pLpoU5ezcMdIszlaUC4ggbOa2h7wVZCanTO79VoeiZLIrCimL4hbtlegpiX6A792jaD5G-cmPhMRGqn2rZcbwIx61e1z3Lz_Wag4lc8I2UwSMFUaIFi67OWN9608JgNNv2-W2uj5NpTFNJSBGUO6gfdOt1C-dgAafhXyPyyQ9m1Uq_0JMwaOkqkkTjW5UNKBacx8Hi9S2AVX7Ln9DN2mNFtFZVCmpnS2qKwd53yhcGQWr_1QL3kshTH5-hkpnLr7ntWIf094NGClp9l5Y2BOB-NqO7JecD_3WHxzjh_3jx6yAiSc3FqX9zmNmiOyIlENc6GHDe10a6p3NNZkI3jTO6C6fQfzOFCQ544htxF7JvxahKLazpSIBRkbf7Hxgdo5s8p8kH5S8HTpl5hdCOsMveJjH0rYU801iTF7Sv5rqn_Zd9FGkT98mjhGl8O4fhEHd967-GR9KupALmG9LtfA2jKwipAcwxyhaXFg2hobCpSvHx9KLOW-3gQt93PqNoE9TAGyIlYbHBFyN3IDsH5bKDYkL4C7RlXUFogBq64SpljjXoW3gYmH2guEaXMwMLf7Mogaoi0Or4ubitxd8EvFuhH2W1TekVc",
  "e": "AQAB"
}

I try to parse the key and round-trip it back to JSON:

const pk = new PublicKeyInfo()
pk.fromJSON(k.publicKey)

console.info(pk.toJSON())

This yields:

{
  "kty": "RSA",
  "n": "AtSHgbWZ-5MHNh8LpVD4-2lOjLitwGjADZ8gEcs3EqskGl1E7Lna8oGRt6V-0yiGwicgNgWPVRW3M4aK8kXe9izb1O43I20A2QVfmZDZB7inS23hrj9PZs863x497-WMdiyBBa3SVrg0StU_vQ8iUFYi5ihQr0b58IKJhVHA6AhqpuUeCbbTakoH1btzOlfqWb6chlL2bT-1KY1EUSRN25Qrfk5T7wV59QvbkGMUuHJRreh6caTASf3cGEG6nk_2YXTiZ6Yyc5XzR0hNervbwa9WVPc19iCP9fNJ8T6oFmJsJ-T9MnEQqttDSOYGwhnzleV4FWrv0jiWhC1-LMdJ-rdHVXPUH9pKArXwWu1FZBk8EG4o3uAB5rcxgk7Z_5sV3PAXQlAISZl3IwauWcDaWIgckDUU3AmzpdrddPn8IiqVtSpcTMISi2MkKJw1iom97iQk8V0dkPvCpFB1wzOoEJfL-gcl61ePeU5xohzy0eQcwjsGAtuK6XgT_TB_u7Q6_FbS0AwySISYz6JsnV-FHsb-0FMUjj6-jF0A3vb7El43xwZUrAhx7qqn_DuvrztjChsNWyE7dKWDceTwxIHDobEG7LDivMvsq-jkRYIzYoMJabrIzTgRjGBLruxBp8Zl1CuOepD4vFO6JBzbZl5Qy0hrpuP9YAlYBg3sBhwsYcrATZWVYcNRkJDsNIo-lSFNOl8DalFm7IsxW0A6AMuysLzm4oLZe2hDrmfRI9Mh5JBgio8cKetZan-0pLpoU5ezcMdIszlaUC4ggbOa2h7wVZCanTO79VoeiZLIrCimL4hbtlegpiX6A792jaD5G-cmPhMRGqn2rZcbwIx61e1z3Lz_Wag4lc8I2UwSMFUaIFi67OWN9608JgNNv2-W2uj5NpTFNJSBGUO6gfdOt1C-dgAafhXyPyyQ9m1Uq_0JMwaOkqkkTjW5UNKBacx8Hi9S2AVX7Ln9DN2mNFtFZVCmpnS2qKwd53yhcGQWr_1QL3kshTH5-hkpnLr7ntWIf094NGClp9l5Y2BOB-NqO7JecD_3WHxzjh_3jx6yAiSc3FqX9zmNmiOyIlENc6GHDe10a6p3NNZkI3jTO6C6fQfzOFCQ544htxF7JvxahKLazpSIBRkbf7Hxgdo5s8p8kH5S8HTpl5hdCOsMveJjH0rYU801iTF7Sv5rqn_Zd9FGkT98mjhGl8O4fhEHd967-GR9KupALmG9LtfA2jKwipAcwxyhaXFg2hobCpSvHx9KLOW-3gQt93PqNoE9TAGyIlYbHBFyN3IDsH5bKDYkL4C7RlXUFogBq64SpljjXoW3gYmH2guEaXMwMLf7Mogaoi0Or4ubitxd8EvFuhH2W1TekQ",
  "e": "AQAB"
}

The final few characters of the key are different - "...TekVc" vs "...TekQ"

This appears to be because the fromJSON method rounds the modulus to the nearest power of 2.

https://github.com/PeculiarVentures/PKI.js/blob/97673f29debafdda7a8899f3f88ea4a5eb6400df/src/RSAPublicKey.ts#L145

If I remove the array.slice it works as expected.

Is this a bug or does PKIjs only support RSA keys that have lengths of a power of 2?