在node.js中解密使用A128CBC-HS256加密的JWT

8 浏览
0 Comments

在node.js中解密使用A128CBC-HS256加密的JWT

我一直在尝试解密载荷,这是一个JSON Web Token,应该作为OAuth2流程的用户数据部分包含个人信息。根据我在JWT上的阅读,它包含三个部分:头部、载荷和签名 - 由点分隔的base64编码字符串。

所讨论的JWT是这样的:

eyJjdHkiOiJKV1QiLCJhbGciOiJSU0EtT0FFUCIsImtpZCI6IkJGTDBzcVpEZEtPdnBEX29YSllPNDhlbEhQaldTWVB1WmZSczBtT3VLMUEiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.GFxv1iIUdktUO9f-pf_eS_J34QnBHJdSJPokE3p5XE1nPCRwIYmf3n4kq4X9T7tOAvOIEs7-BoeFedzjRQnXKetrLY5wWHCALt4C_Y8Ibu--WseiQJnIKzyEvuhZHonRN6GWaMZB724M2NhtHHXY4pLX7RNsXquaMBFG1sFny20zHWEjSGx4jDOfKkH-f9Ty5hRIKvZXmQ36RsJI4oF1i4j1aPZj-BKiyiorm5c5F-IUcukhm2QObf88K3EFS0mbVvPM7yNAure51LWptBLIKBBq7VPMfq0NXLL_bBzMZ1XdFBDt2qkIteoE9ts44esTeVvsvNSRHGqAtl8EO-10wg.jOvZCvp2DULxkMyiybRjXw.CCeHLVU2GjsSrdND6UYxIN9Ny_QKig7CC_E3uDsHsb1mRaDV9gQ432NGYpD0RndPQoepOppcDsI2zT2yoKCYLYKuig6XDcOl3eK4-MooDjZOHn_9ahYlAiauTFRtiJfHU9rTSMU_eLkH-z1eyzoe3fbEqkK6hWxHELzlYByeof0pINcDRsxwcNG0GDAqrcJ3IdQjLwoupVGLZh-wb3WsqpZbV5Abz2LkV3BK_TqVjlEBEtKBXOZohdieIwEo1kUm_MZJpXzF6HIJkasrrN1c3-uVmMMJbRBDfZv0GBZ4OyNv9q5vTKCY90RF3QVmN604L9v2JAalOmhLgRq1q8on_dk35nKuhynSrr9lMy2ieTD5VcpbDODpwGHPBQJnn99dbYZqu3uWKYURR2mmfCq1IDEgtq3aczgmNmU6QKQ8vUgljSQ75cqwS9GaHHPHuJZeMXRa1ifkuywf7z5kgk8Z4z_jKA1fqnlYSmRASponkuHqkVx-P5ZlRqfjvR9qpG2qz3B4a1Cjmnp2Di8_5jTg09CLYKBMfa42Fgw5lnlivEcGvWIWWd4a0FvYQlDCjDkRfv21DFkleJ23CyJ7Zjsm2CTPZXk9y6G3HzOYgFxyriIw_52VpnzIrgmYsmpm5amBKGbYYeZbthPwVnf1W76yqBziYljAoIP7g1uM0HdjvkqeDTe3Q5_WQAdrmIz8Yjh2z0edjc0ynPPqKLMfEs8SQWMYsodgQ6KcVMGWalYPCV6eF79Ldf5gpah_oXTMP0nn7rKccoiftlNFsgem2p81yTN7AwWKm_fO70EFdpQ1-kez7lQ5OtamdZWR-W3sEtn3K0wdeLbMYtD4bD8RdwKoZ_DZgBLdJenmXAa7P5dkOzxaeUAKTAaYOSq_EKxIH8AtnqyTTXEfRXLxyoFGJlN_N6bSUWytbJr4c1ktxBG4RKWWJpusVA2hiZ2GCFs7PfWRPC7hSFd8V52O1hwuZsAz6BN4pJv1rIicVSJNozMgyv9ZqY5HkOTIUUztsu_Urkre1ItfVcAg1Ia5Fj-OZ7ymm7sNA9JKBV14T4EPtfAcnoLLRr95ngTzsBPu7KKb-EO7k7m1na_sisQaQxlQNJset5_Hi_Oj2Sj1g7tB7Uld64MlQbvOBxBIw_D9hmmjm_v1cbDcLV2XmmXQotLout197vcJahNQOvSb7W9BqXFvxVlSHa89_H75acO4IMYem3lRJXT2ZdwsQhvFZ8BRSN7h-kKl6Z_v3aRNTrbwA_qQDYlH67uP84F9FKqejejCgNGtqzbvNs4SYv64Wsq9Uz6xhAeCXBuxn9EQc83cKsNkUnLwREHTlng3CpQHpZje6dAEpKKOIN5XHOcj04BNwAZP0TnCeGUWqZpxPI3vyFupC5vb5Wt26BOC1MWb0Upn08xAxwY5urtkX4cRFMpnXFHnv-ypfr2UY5KP6Nh2tbahEgZ-1bBw3GaEPYAqros31pyY6E51nCQ2j3kdmFxVuW3fTp5CzHpAPuTSi6zX6r8sttUi-bJK81CTey8TMFtr5sqpYtlLHbUpSsi-YfYeNCfOmSMLESMQRDSh7LmBFbGK9zDavuTALTNMNPVWeJUQOeAcScQWFZLEg8-attDjdcpxVEZAJIXb9frYD4aDyE4WE0vsRj-kP3d0txJ1_c-mG-PjW0_IVIo_9bUHteHGZdyMS1y6NNOhoTlq0XXAs0oRcd7RVojwUYpbVGAvWT7_CDPTKvnJDFALbAu2D7KWFw1dCnDrUW5HzxW274Y0wx25ev3BKpVE5tekBujVNVmqNjIh._JyU-CpPzHItUbTb_syKsg

该载荷来自于芬兰政府使用的一个服务,所以我猜测它的格式应该是正确的,但我首先困惑的是JWT包含五个部分。第一部分是头部:

{"cty":"JWT","alg":"RSA-OAEP","kid":"BFL0sqZDdKOvpD_oXJYO48elHPjWSYPuZfRs0mOuK1A","enc":"A128CBC-HS256"}

载荷应该使用以下公钥/私钥进行加密:

const jsonKey = {
  p: '7C8pWx6iaZDypKgElaJoDGN_OdZh-mAI6jAZkoA9Io5vQrTNzqdFyTF1j_AsU4KMKATvihtKoTAnZnfH1Dk-nCX6GLpiDOeZAXyv-tTGfINl50YhbI-qu4B8h-CPohzOXpBMrOCplQwR60NcW827aNVu1OTBPRboWgtAyqduWGE',
  kty: 'RSA',
  q: '3Pxz70nzwiNWQwfXQEXA529HoGP6aFBFY2HRnOWF1M7OlN4OnHE-WRlUeyMFA1junBOtUbBhq8hO3X0zPNZVwUrA1IbzoBZUmCTaL4ClZ6dDATfFMrebj8455wCqJNfpkiAXLhA4eh5j1daAWqMyhr9skx5ZslSYbeRM52zmWUc',
  d: 'l6a9RMaox9dYchDoOWHZ_IpXLfZZyN2k47fljDluwkIs4wCGjBbvt9nAX2mjsNttWi7mihLcea0PO5wt9dHhzwrB9xbAKlHNh4_IK9YJhdCg47rECtdDhIHqnvTHx4zYWViC6MBorR094pOQy57Hg2kkJhVkeTLeruBmL1QFf7AkoIICJ11FCIwYHJW8bRfWTBbqh8Rnwq2z620ZE16ZsHTp1TfXWWyOXIuMZXAZfdiQq95zR6npkEdGs_es8mwqgXroXmE2UQMEz-r-9DpTXk3_cbXLFbo8PhrpfD8Mxe8hQOdkD5yGqzGz4Xgnl62iCTRZOwdxH3ayH6z9vXDTAQ',
  e: 'AQAB',
  use: 'enc',
  kid: 'BFL0sqZDdKOvpD_oXJYO48elHPjWSYPuZfRs0mOuK1A',
  qi: 'XCkgo29q4ha8iwGc9VJq9y2TsAK7WxjcTZlcOoYFkJqzAdxlBvYKBJ4H_2OQvURo5sVhwWQbHrd_nfHVKe8vos9AYz3b0ylQJODse8Xm2w3gaTrwdb4Z5EN2I_2513O60XIeg2WSLMSkvkfaSkJ20OCM7OeZwVyE_N8dTyafy84',
  dp: 'dw1y0D6J6aKp3Lvgy7h4sD37JKFe9AEynTGvwjwoFOItTTesQk3pDHiE5RBQl6vHkGikgj4tiUCnq6wXK2_LkpRGE-7ne8_GPYynfE2C28K0PDcKpBlrG2ax3yAf5ryUffBI5h-8-6eA5NEonhH_NOHZIzFIAs4oQzNG7qAlLCE',
  alg: 'RS256',
  dq: 'WpjVHuD-ojTChLCOOrdeIoOopcTXQDTIfbn4qY4fk-NFJhrzeoeiu_x6ehEdWQX4rNwUTk01faudSYiunN5yQdBXxcmdz5_YBpf1K0xeg2Q7QCCRI_3KNOajLmVDW994zoOBfU0BGm-jFmPeM0p8yGlqJdZnh4jPBR53uNkYhrk',
  n: 'y-Fw7PfbnBie2s408nZICscdQ0-spOTeli0LIkFi5QMgGnQ2mQlTXcypm8UdkYu-Up4tzFUmkd-n0gPKES6cP1YGWn9gXC9DP1GmHQVXuGGAxMLkctYK2-CSCckgLtNcmxzdEtwbtwOmWHFdtBUFvwLKnqU0XEv_wdFEakKHwp12foSUoUH7FbzMbLu5BHo4rjuTU2paHQpiHqoG9qNg-jZFXLdjRGWslJKCJGDUBXB3HIlGykr8ghOdsMlpzRn3zQ8WI77bPN58QlGMXVOQcKivsKhoF9mZOHEceAfPLKgucmI-KwJ7w-6DTAuwCI6eo6hlQc_Gz0JxjPJdH3o75w'
}

目前我只能使用这个库解密载荷:

const { Crypto } = require('@peculiar/webcrypto')
const crypto = new Crypto()
// 上面定义的载荷
const parts = payload.split('.')
function ab2str (buf) {
  return String.fromCharCode.apply(null, new Uint8Array(buf))
}
const decrypt = async () => {
  try {
    const k = await crypto.subtle.importKey('jwk', jsonKey, { name: 'RSA-OAEP', hash: 'SHA-1' }, false, ['decrypt'])
    const data = await crypto.subtle.decrypt('RSA-OAEP', k, Buffer.from(`${parts[1]}`, 'base64'))
    return ab2str(data)
  } catch (err) {
    console.log(err)
  }
}
decrypt()

解密得到的结果是ñDõ^îó"ìût=Z]¬úí³ê,它不是一个JSON对象。其他部分(或它们的组合)会导致库中的错误。改变载荷或密钥中的任何内容都会抛出异常,所以我猜测阶段应该是正确的,但输出结果不正确。

我的问题是:我如何使用node.js解密这个载荷,或者它实际上是有问题的吗?

附注:私钥和JWT使用的是测试环境,所以它们不包含任何真实的机密信息。

0