2015-06-17 14 views
6

Tôi là lập trình viên C++ khá mới (tôi vẫn còn ở trường đại học nên tôi cho rằng tôi là một lập trình viên khá mới) và tôi đang cố gắng tạo ra JWT trong C++. Tôi có thể tạo ra và mã hóa một tiêu đề và tải trọng, nhưng chữ ký tôi tạo ra bằng cách sử dụng thư viện hmac openssl có vẻ là không hợp lệ khi tôi kiểm tra nó trên jwt.io. Tôi có một cảm giác này là do một số sai lầm sắc thái tôi chỉ không nhìn thấy. Nếu bạn có thể tìm thấy lỗi của tôi, tôi sẽ đánh giá cao nó. Nếu bạn cũng có đề xuất về cách cải thiện mã của tôi nói chung cũng sẽ được đánh giá cao. Lưu ý tôi phải sử dụng openssl và boost cho json.JWT (Mã thông báo Web JSON) bằng C++ sử dụng lỗi tăng và lỗi mở

**** CẬP NHẬT ****

tôi phát hiện ra rằng thêm dòng mới đã được bổ sung và điều này gây ra sai sót trong quá xác thực. Hiện nay tôi đang kêu gọi str.erase để loại bỏ chúng nhưng nếu ai đó có thể cho tôi biết nơi họ đang đến tôi sẽ đánh giá cao nó vì vậy tôi có thể tránh được việc phải thao tác chuỗi


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 ""; 
} 

Đây là phương pháp tôi sử dụng ký 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()); 
} 

Đây là cách tôi mã hóa dữ liệu trong 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()); 
} 

Trả lời

4

OpenSSL i nserts ký tự dòng mới sau mỗi ký tự 64, bạn có thể tắt tính năng này bằng cách sử dụng:

BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); 

Xem the documentation tại đây.

Trong khi kiểm tra mã của bạn tôi cũng tìm thấy 2 vấn đề sau:

1) Bạn bỏ qua ký tự cuối cùng của bộ đệm khi thực hiện nó URL-an toàn. Bạn nên loại bỏ - 1.

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

2) Khi thực hiện đầu ra Base64 URL-an toàn, bạn cần phải thay thế '+' với '-' và '/' với '_'. mã của bạn đã có cách khác xung quanh. Vì vậy:

case '+': 
    ss << '-'; 
    break; 
case '/': 
    ss << '_'; 
    break; 
Các vấn đề liên quan