2015-06-17 6 views
6

Ich bin ein ziemlich Anfänger C++ - Programmierer (ich bin immer noch in der Schule, so nehme ich an, ich bin ein ziemlich Anfänger Programmierer im Allgemeinen) und ich versuche zu generieren JWT in C++. Ich bin in der Lage, einen Header und Payload zu generieren und zu kodieren, aber die Signatur, die ich mit der hmac-Bibliothek von openssl erstelle, scheint ungültig zu sein, wenn ich sie auf jwt.io überprüfe. Ich habe das Gefühl, dass dies auf einen nuancierten Fehler zurückzuführen ist, den ich gerade nicht sehe. Wenn Sie meinen Fehler finden, werde ich es sehr schätzen. Wenn Sie auch Vorschläge haben, wie Sie meinen Code im Allgemeinen verbessern können, wäre das auch eine gute Idee. Hinweis: Ich muss OpenSSL und Boost für Json verwenden.JWT (JSON Web Token) in C++ mit boost und openssl bug

**** UPDATE ****

Ich entdeckte, dass zusätzliche neue Linien hinzugefügt wurden und dies verursachte Fehler bei der Authentifizierung. Ich str.erase zur Zeit nenne sie zu entfernen, aber wenn jemand könnte mich wissen lassen, wo sie mich kommen würde es zu schätzen wissen, so kann ich vermeiden, dass die Zeichenfolge


char* Auth::genJWT() 
{ 
    ptree pt; 
    std::stringstream jwt; 

    //Make and encode header 
    pt.put("typ","JWT"); 
    pt.put("alg","HS256"); 
    std::ostringstream buf; 
    write_json(buf, pt, false); 
    std::string header = buf.str(); 
    jwt << base64_encode((unsigned char*)header.c_str(), (int) header.length()); 

    //clear buffer 
    pt.clear(); 
    buf.clear(); 
    buf.str(""); 

    //make pay load 
    pt.put("org_guid", Config::organization_guid); 
    pt.put("agent_guid", Config::agent_guid); 
    write_json(buf, pt, false); 
    std::string payload = buf.str(); 
    jwt << '.' << base64_encode((unsigned char*)payload.c_str(), (int) payload.length()); 

    //sign data 
    std::string signed_data = signToken(jwt.str()); 
    jwt << '.' << base64_encode((unsigned char*) signed_data.c_str(), (int) signed_data.length()); 

    //jwt made 
    std::cout << "JWT Token: " << jwt.str() << std::endl; 

    //Note I am testing by copying the token into an online debugger 
    //returning "" is not my bug 
    return ""; 
} 

Dies ist die Methode, die ich verwende zu manipulieren, mit unterzeichnen das Token

std::string Auth::signToken(std::string to_sign) 
{ 
    //std::string key = Config::secret; 
    std::string key = "foo"; 

    unsigned int len = 32; 
    unsigned char signed_data[32]; 

    HMAC_CTX ctx; 
    HMAC_CTX_init(&ctx); 

    HMAC_Init_ex(&ctx, &key[0], (int) key.length(), EVP_sha256(), NULL); 
    HMAC_Update(&ctx, (unsigned char*)&to_sign[0], to_sign.length()); 
    HMAC_Final(&ctx, signed_data, &len); 
    HMAC_CTX_cleanup(&ctx); 

    std::stringstream ss; 
    ss << std::setfill('0'); 

    for(unsigned int i = 0; i < len; i++) 
    { 
     ss << signed_data[i]; 
    } 

    return (ss.str()); 
} 

Dies ist, wie ich die Daten in base64Url

std::string Auth::base64_encode(const unsigned char* input, int length) 
{ 
    BIO *bmem, *b64; 
    BUF_MEM *bptr; 

    b64 = BIO_new(BIO_f_base64()); 
    bmem = BIO_new(BIO_s_mem()); 
    b64 = BIO_push(b64, bmem); 
    BIO_write(b64, input, length); 
    BIO_flush(b64); 
    BIO_get_mem_ptr(b64, &bptr); 

    std::stringstream ss; 

    //make URL safe 
    for(unsigned int i = 0; i < bptr->length - 1; i++) 
    { 
     switch(bptr->data[i]) 
     { 
      case '+': 
       ss << '_'; 
       break; 
      case '/': 
       ss << '-'; 
       break; 
      case '=': 
       //don't add in padding 
       break; 
      default: 
       ss << bptr->data[i]; 
       break; 
     } 
    } 

    BIO_free_all(b64); 
    return (ss.str()); 
} 

Antwort

4

OpenSSL kodieren i nserts ein Newline-Zeichen nach jedem 64'th Charakter, können Sie dies durch die Verwendung deaktivieren:

BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); 

the documentation hier.

Während Ihr Code Testen fand ich auch die folgenden 2 Probleme:

1) Sie das letzte Zeichen des Puffers überspringen, wenn es URL-Safe. Sie sollten die entfernen - 1.

for(unsigned int i = 0; i < bptr->length ; i++) 

2) Wenn der Base64 Ausgang URL-sicher zu machen Sie müssen '+' mit ersetzen '-' und '/' mit '_'. Dein Code hatte das anders herum. Also:

case '+': 
    ss << '-'; 
    break; 
case '/': 
    ss << '_'; 
    break;