如何用C语言结合OpenSSL生成JWT.io与Google认可的JWT?
C语言原生OpenSSL生成Google合规JWT的问题排查
我要开发一款X应用,必须通过C语言结合原生OpenSSL生成可用于登录Google服务的JWT,其他方案无法满足需求。目前已经用PHP的openssl_sign函数成功实现该功能,但基于OpenSSL 1.0.2编写的C代码始终无法生成JWT.io与Google认可的JWT。
以下是我的C代码:
#include <openssl/evp.h> #include <openssl/pem.h> #include <stdio.h> #include <stdlib.h> #include <string.h> void getsha(char* msg, char* hash) { // This function wont work, yet it returns a 256 byte value as hash. // I'm given a key. let's assume its this (but more extravagant). char* pky = "-----BEGIN PRIVATE KEY-----\nAAAAAAAAAAA==\n-----END PRIVATE KEY-----\n"; unsigned int psz = strlen(pky), msz = strlen(msg), len = 0; memset(hash, 0, 384); // wipe out output hash OpenSSL_add_all_digests(); BIO* IO = BIO_new_mem_buf(pky, psz); // make a buffer? struct evp_pkey_st* SK = PEM_read_bio_PrivateKey(IO, NULL, NULL, NULL); // error out if function fails if (!SK) { // we reach here if we use the example private key above, but if you replace // it with a real private key, this test will pass. BIO_free_all(IO); EVP_PKEY_free(SK); printf("Error getting key\n"); exit(-1); } EVP_MD_CTX* X = EVP_MD_CTX_create(); // We want SHA256 key if (!EVP_SignInit(X, EVP_sha256())) { printf("Error getting digest\n"); exit(-1); } // We want to add our generated JWT if (!EVP_SignUpdate(X, msg, msz)) { printf("Error updating key/digest\n"); exit(-1); } // Then we sign the key // This function gives warnings if the string isn't an unsigned char // but does that matter if I'm only feeding in base64 values? EVP_SignFinal(X, (unsigned char*)hash, &len, SK); // Free allocations BIO_free_all(IO); EVP_PKEY_free(SK); EVP_MD_CTX_destroy(X); } char* b64enc(const char* in, char* res, const int bufsz) { // Use modified lookup table because today's base-64 standards are different // when dealing with JWT const char* lut = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; // get output pointer and size of input int n = 0, insz = strlen(in); char* rp = res; // exit if input buffer is too small but we made large buffers for our test so // this shouldn't happen. if ((insz / 3) * 4 + 2 > bufsz) { return NULL; } // wipe out output buffer memset(res, 0, bufsz); while (n < insz) { unsigned long d = 0, n2 = 0, gotbytes = 0; // shove up to 3 characters into a 32-bit buffer (defined as unsigned long // d) while (n2 < 3 && n < insz) { d = (d << 8) + in[n]; n++; n2++; gotbytes++; } // Keep shoving in binary 0's until 24 bits are shifted in. while (n2 < 3) { d = (d << 8); n2++; } // Output is stored backwards so we make it forwards but only giving 6 bits // (hence anding with 0x3F) *rp++ = lut[(d >> 18) & 0x3F]; *rp++ = lut[(d >> 12) & 0x3F]; if (gotbytes >= 2) { *rp++ = lut[(d >> 6) & 0x3F]; } // input bytes >= 2 means 3 bytes in base64 if (gotbytes >= 3) { *rp++ = lut[d & 0x3F]; } // input bytes >= 3 means 4 bytes in base64 } return res; } int main() { // Setup our header and claims for JWT char* jwtheader = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"; char* claims = "{\"scope\":\"https://www.example.com/auth\"}"; // set char array size of each element int bufsz = 2048; // feed each char array from ssl array to not make memory fragments char ssl[11000], *tmp2 = ssl, *tmp = ssl + bufsz, *headerdotclaims = ssl + (bufsz * 2), *sha256val = ssl + (bufsz * 3), *result = ssl + (bufsz * 4); // and erase the whole space in ONE operation memset(ssl, 0, 10999); // Base64 encode JWT values and combine them with a dot. sprintf(headerdotclaims, "%s%c%s", b64enc(jwtheader, tmp2, bufsz - 1), '.', b64enc(claims, tmp, bufsz - 1)); // Get SHA256 value of above. (apparently never working) getsha(headerdotclaims, sha256val); // Add a dot and the base64 encoded version to the result sprintf(result, "%s%c%s", headerdotclaims, '.', b64enc(sha256val, tmp, bufsz - 1)); // and show it printf("%s", result); }
请问我的代码中存在哪些问题,导致无法生成符合要求的JWT?
内容的提问来源于stack exchange,提问作者mike_s
相关产品推荐
相关产品推荐

