使用openssl和C ++验证JWT的确切base64 url​​解码规则和实现是什么

时间:2019-07-31 13:41:23

标签: c++ openssl jwt base64url

我对openssl接口和base64解码规则非常陌生,并尝试使用以下解决方案来验证使用私钥(RS256 alg)签名的JWT:Segmentation Fault while verifying JWT token using a public key through openSSL in C++但我的示例JWT无法验证。

我仅不具备base64 url​​解码功能,因此我按照自己的理解手动执行了这些步骤-在调用我的base64解码功能之前,我先替换了'-'->'+'和'_'->'/' 。为了获得正确的签名长度,我还必须手动添加填充('=')。是否存在我缺少的base64 url​​解码规则,或者首先替换符号的方法是否以任何方式错误?

我首先尝试使用RSA_verify,但错误是相同的。

使用python和在线JWT验证来验证相同的令牌和密钥,因此应该可以。我在gdb上的b64解码中以b64解码之后以及在python上的urlsafe_b64decode之后打印了签名,并且它们的值是相同的(除了python版本末尾的一些符号),这甚至使人们相信替换策略应该是工作。

header: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
body: eyJhdWQiOlsiYXBpLXJlc291cmNlIl0sInNjb3BlIjpbInJlYWQiXSwiZXhwIjoxNTYzNDUwODkzLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMzVhYmVjZDEtNjcxMi00M2M3LWE4MDItZjg3MGYzMTY4MmI0IiwiY2xpZW50X2lkIjoidGVzdCJ
sig: ZCXtI2nN+d0Cn5dgb3K9JMI41nrEaK/AVSMRG9c5cyZqXpnMQETfGcDEs0jPzmRh+jDc+Kuq53naOtjkItMcR/vYPn72dKZ4Fpp8mvOAZXypkVCLzof3Lsxrtqq9G3V4LNTuOHiXW/q+9mEu51zWg1HDr1+rSt3YXkFFSWp5e4MWS2TNP1MB7lBbZC+kdMZ/GqZ9lrfNo2YqJR7tqcHOrfOmFTzqxVivEB8s+A0iEv/MwdlS6LpJBKU9+d94i1P9Lsqzlg7b/0ekRoYJEG4DXeNp2zxxBxZ1u3FBlIbyJoOGDmX+EU4A5eh2RlDdEvG1YF/zcMARpP1bFV86WTSOuQ==
Error verifying message: error:04091068:rsa routines:INT_RSA_VERIFY:bad signature
error:04091068:rsa routines:INT_RSA_VERIFY:bad signature

错误是:

module.exports = {
  create(req, res) {
    var hexTag = shortid.generate();

    let password = req.body.password;
    bcrypt.genSalt(10, function(err, salt) {
      bcrypt.hash(password, salt, function(err, hash) {
        return Player
        .create({
            hexTag: hexTag,
            mail: req.body.mail,
            password: hash,
            pseudo: req.body.pseudo
        })
        .then(player => res.status(201).send(player))
        .catch(error => res.status(400).send(error));
      });
    });
  }
};

1 个答案:

答案 0 :(得分:0)

这是我使用的base64_url_decode。我没有写它,但找不到从哪里得到它。

使用以下代码,您还有问题吗?

/*
Base64 translates 24 bits into 4 ASCII characters at a time. First,
3 8-bit bytes are treated as 4 6-bit groups. Those 4 groups are
translated into ASCII characters. That is, each 6-bit number is treated
as an index into the ASCII character array.

If the final set of bits is less 8 or 16 instead of 24, traditional base64
would add a padding character. However, if the length of the data is
known, then padding can be eliminated.

One difference between the "standard" Base64 is two characters are different.
See RFC 4648 for details.
This is how we end up with the Base64 URL encoding.
*/

const char base64_url_alphabet[] = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
};

std::string base64_url_encode(const std::string & in) {
  std::string out;
  int val =0, valb=-6;
  size_t len = in.length();
  unsigned int i = 0;
  for (i = 0; i < len; i++) {
    unsigned char c = in[i];
    val = (val<<8) + c;
    valb += 8;
    while (valb >= 0) {
      out.push_back(base64_url_alphabet[(val>>valb)&0x3F]);
      valb -= 6;
    }
  }
  if (valb > -6) {
    out.push_back(base64_url_alphabet[((val<<8)>>(valb+8))&0x3F]);
  }
  return out;
}

std::string base64_url_decode(const std::string & in) {
  std::string out;
  std::vector<int> T(256, -1);
  unsigned int i;
  for (i =0; i < 64; i++) T[base64_url_alphabet[i]] = i;

  int val = 0, valb = -8;
  for (i = 0; i < in.length(); i++) {
    unsigned char c = in[i];
    if (T[c] == -1) break;
    val = (val<<6) + T[c];
    valb += 6;
    if (valb >= 0) {
      out.push_back(char((val>>valb)&0xFF));
      valb -= 8;
    }
  }
  return out;
}

更新

您的问题不是base64解码,而是此行:

decoded_body.append(token.begin()+ token.find('.')+1, token.begin() + token.rfind('.')-1);

你一个人出局。 coded_body缺少最后一个字符。如果将其更改为以下内容,则可以正常运行:

decoded_body.append(token.begin()+ token.find('.')+1, token.begin() + token.rfind('.'));