Guest User

https://stackoverflow.com/questions/74963265/ecdsa-signature-generated-with-mbedtls-not-verifiable-i

a guest
Dec 30th, 2022
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.80 KB | Help | 0 0
  1. #include <NTPClient.h>
  2. #include <WiFiUdp.h>
  3. #include <WiFi.h>
  4. #include "mbedtls/md.h"
  5. #include <mbedtls/pk.h>
  6. #include <mbedtls/error.h>
  7. #include <mbedtls/entropy.h>
  8. #include <mbedtls/ctr_drbg.h>
  9. #include <base64.h>
  10. #include "base64.hpp"
  11. #include <ArduinoJson.h>
  12.  
  13. //The device name
  14. #define DEVICE_NAME "a name"
  15. //The SSID of your WiFi network.
  16. #define SSID "a ssid"
  17. //The password to access your WiFi network.
  18. #define WIFIPASSWORD "a password"
  19.  
  20. String ecc_priv = \
  21. "-----BEGIN EC PRIVATE KEY-----\r\n" \
  22. "MHcCAQEEI.......................................................\r\n" \
  23. "................................................................\r\n" \
  24. ".................................\r\n" \
  25. "-----END EC PRIVATE KEY-----";
  26.  
  27. String ecc_pub = \
  28. "-----BEGIN PUBLIC KEY-----\r\n" \
  29. "MFkwEw.........................................................\r\n" \
  30. "...........................................................\r\n" \
  31. "-----END PUBLIC KEY-----";
  32.  
  33. WiFiUDP ntpUDP;
  34. NTPClient timeClient(ntpUDP);
  35.  
  36. String extractHeader(String _token){
  37.   String result;
  38.   int first = _token.indexOf(".");
  39.   result = _token.substring(0,first);
  40.   return result;
  41. }
  42.  
  43. String extractPayload(String _token){
  44.   String result;
  45.   int first = _token.indexOf(".");
  46.   int second = _token.indexOf(".", first+1);
  47.   result = _token.substring(first+1,second);
  48.   return result;
  49. }
  50.  
  51. String extractSignature(String _token){
  52.   String result;
  53.   int first = _token.indexOf(".");
  54.   int second = _token.indexOf(".", first+1);
  55.   result = _token.substring(second+1);
  56.   return result;
  57. }
  58.  
  59. String extractHeaderAndPayload(String _token){
  60.   String result;
  61.   int first = _token.indexOf(".");
  62.   int second = _token.indexOf(".", first+1);
  63.   result = _token.substring(0, second);
  64.   return result;
  65. }
  66.  
  67. static char* mbedtlsError(int errnum) {
  68.     static char buffer[200];
  69.     mbedtls_strerror(errnum, buffer, sizeof(buffer));
  70.     return buffer;
  71. }
  72.  
  73. bool verifyJWT(String _token){
  74.   timeClient.update();
  75.   int ts = timeClient.getEpochTime();
  76.   byte *pkeybuffer = (byte*)malloc((ecc_pub.length()+1)*sizeof(byte));
  77.   ecc_pub.getBytes(pkeybuffer, ecc_pub.length() + 1);
  78.   mbedtls_pk_context pk_context;
  79.   mbedtls_pk_init(&pk_context);
  80.   int rc = mbedtls_pk_parse_public_key(&pk_context, pkeybuffer, ecc_pub.length() + 1);
  81.   if (rc != 0) {
  82.     printf("Failed to mbedtls_pk_parse_public_key: %d (-0x%x): %s\n", rc, -rc, mbedtlsError(rc));
  83.   }
  84.   free(pkeybuffer);
  85.   String headerandpayload = extractHeaderAndPayload(_token);
  86.   byte *headerandpayloadbytes = (byte*)malloc((headerandpayload.length()+1)*sizeof(byte));
  87.   headerandpayload.getBytes(headerandpayloadbytes, headerandpayload.length() + 1);
  88.   String signature = extractSignature(_token);
  89.   signature.replace('-','+');
  90.   signature.replace('_','/');
  91.   while(signature.length() % 3 != 0){
  92.     signature += "=";
  93.   }
  94.   byte *signatureb64bytes = (byte*)malloc((signature.length()+1)*sizeof(byte));
  95.   signature.getBytes(signatureb64bytes, signature.length() + 1);
  96.   unsigned int siglength = decode_base64_length(signatureb64bytes, signature.length());
  97.   byte *signaturebytes = (byte*)malloc((siglength)*sizeof(byte));
  98.   decode_base64(signatureb64bytes, signature.length(), signaturebytes);
  99.   free(signatureb64bytes);
  100.   uint8_t digest[32];
  101.   int rcmd = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), headerandpayloadbytes, headerandpayload.length(), digest);
  102.   if (rcmd != 0) {
  103.     printf("Failed to mbedtls_md: %d (-0x%x): %s\n", rc, -rc, mbedtlsError(rc));
  104.   }
  105.   free(headerandpayloadbytes);
  106.   int ret = mbedtls_pk_verify(&pk_context,  MBEDTLS_MD_SHA256,  digest, sizeof(digest), signaturebytes,  siglength);
  107.     if (ret != 0) {
  108.     printf("Failed to mbedtls_pk_verify: %d (-0x%x): %s\n", rc, -rc, mbedtlsError(rc));
  109.   }
  110.   free(signaturebytes);
  111.   mbedtls_pk_free(&pk_context);
  112.   String b64header = extractHeader(_token);
  113.   b64header.replace('-','+');
  114.   b64header.replace('_','/');
  115.   while(b64header.length() % 3 != 0){
  116.     b64header += "=";
  117.   }
  118.   byte *headerb64bytes = (byte*)malloc((b64header.length()+1)*sizeof(byte));
  119.   b64header.getBytes(headerb64bytes, b64header.length()+1);
  120.   unsigned int headerlength = decode_base64_length(headerb64bytes, b64header.length());
  121.   byte *headerbytes = (byte*)malloc((headerlength+1)*sizeof(byte));
  122.   unsigned int hl = decode_base64(headerb64bytes, headerbytes);
  123.   headerbytes[hl] = '\0';  
  124.   String headerstring = String((char *)headerbytes);
  125.   DynamicJsonDocument headerdoc(128);
  126.   deserializeJson(headerdoc, headerstring);
  127.   String alg = headerdoc["alg"];
  128.   String typ = headerdoc["typ"];
  129.   headerdoc.clear();
  130.   free(headerb64bytes);
  131.   free(headerbytes);
  132.   String b64payload = extractPayload(_token);
  133.   b64payload.replace('-','+');
  134.   b64payload.replace('_','/');
  135.   while(b64payload.length() % 3 != 0){
  136.     b64payload += "=";
  137.   }
  138.   byte *payloadb64bytes = (byte*)malloc((b64payload.length()+1)*sizeof(byte));
  139.   b64payload.getBytes(payloadb64bytes, b64payload.length()+1);  
  140.   unsigned int payloadlength = decode_base64_length(payloadb64bytes, b64payload.length());
  141.   byte *payloadbytes = (byte*)malloc((payloadlength+1)*sizeof(byte));
  142.   unsigned int pl = decode_base64(payloadb64bytes, payloadbytes);
  143.   payloadbytes[pl] = '\0';
  144.   String payloadstring = String((char *)payloadbytes);
  145.   DynamicJsonDocument payloaddoc(128);
  146.   deserializeJson(payloaddoc, payloadstring);
  147.   String exp = payloaddoc["exp"];
  148.   int expint = exp.toInt();
  149.   String aud = payloaddoc["aud"];
  150.   payloaddoc.clear();
  151.   free(payloadb64bytes);
  152.   free(payloadbytes);
  153.   if(alg != "ES256"){
  154.     return false;
  155.   }
  156.   if(expint < ts){
  157.     return false;
  158.   }
  159.  
  160.   if(typ != "JWT"){
  161.     return false;
  162.   }
  163.  
  164.  
  165.   if(ret != 0){
  166.     return false;
  167.   }
  168.   return true;
  169. }
  170.  
  171. String createJWT() {
  172.     String header = "{\"alg\":\"ES256\",\"typ\":\"JWT\"}";
  173.     String base64Header = base64::encode(header);
  174.     timeClient.update();
  175.     int ts = timeClient.getEpochTime();
  176.     uint32_t iat = ts;
  177.     uint32_t exp = iat + 60*60;
  178.  
  179.     String payload = "{\"iat\":" + String(iat) + ",\"exp\":" + String(exp)+"}";
  180.     String base64Payload = base64::encode(payload);
  181.     String headerAndPayload = base64Header + "." + base64Payload;
  182.     headerAndPayload.replace('+','-');
  183.     headerAndPayload.replace('/','_');
  184.     headerAndPayload.replace("=","");
  185.    
  186.     byte *keybuffer = (byte*)malloc((ecc_priv.length()+1)*sizeof(byte));
  187.     ecc_priv.getBytes(keybuffer, ecc_priv.length() + 1);
  188.     mbedtls_pk_context pk_context;
  189.     mbedtls_pk_init(&pk_context);
  190.     int rc = mbedtls_pk_parse_key(&pk_context, keybuffer, ecc_priv.length() + 1, NULL, 0);
  191.     if (rc != 0) {
  192.         printf("Failed to mbedtls_pk_parse_key: %d (-0x%x): %s\n", rc, -rc, mbedtlsError(rc));
  193.         return "SHIT";
  194.     }
  195.     free(keybuffer);
  196.    
  197.  
  198.     mbedtls_entropy_context entropy;
  199.     mbedtls_ctr_drbg_context ctr_drbg;
  200.     mbedtls_ctr_drbg_init(&ctr_drbg);
  201.     mbedtls_entropy_init(&entropy);
  202.  
  203.     const char* pers="some entropy";
  204.                
  205.     mbedtls_ctr_drbg_seed(
  206.         &ctr_drbg,
  207.         mbedtls_entropy_func,
  208.         &entropy,
  209.         (const unsigned char*)pers,
  210.         strlen(pers));
  211.    
  212.     byte *headerAndPayloadbytes = (byte*)malloc((headerAndPayload.length()+1)*sizeof(byte));
  213.     headerAndPayload.getBytes(headerAndPayloadbytes, headerAndPayload.length() + 1);
  214.     uint8_t digest[32];
  215.     rc = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), headerAndPayloadbytes, headerAndPayload.length(), digest);
  216.     if (rc != 0) {
  217.         printf("Failed to mbedtls_md: %d (-0x%x): %s\n", rc, -rc, mbedtlsError(rc));
  218.     }
  219.  
  220.     free(headerAndPayloadbytes);
  221.     byte *oBuf = (byte*)malloc(5000*sizeof(byte));
  222.     size_t retSize;
  223.     rc = mbedtls_pk_sign(&pk_context, MBEDTLS_MD_SHA256, digest, sizeof(digest), oBuf, &retSize, mbedtls_ctr_drbg_random, &ctr_drbg);
  224.     if (rc != 0) {
  225.         printf("Failed to mbedtls_pk_sign: %d (-0x%x): %s\n", rc, -rc, mbedtlsError(rc));
  226.     }
  227.     unsigned int osize = encode_base64_length(retSize);
  228.     byte *output = (byte*)malloc((osize+1)*sizeof(byte));
  229.     encode_base64(oBuf, retSize, output);
  230.     String sig = String((char*)output);
  231.     free(output);
  232.     sig.replace('+','-');
  233.     sig.replace('/','_');
  234.     sig.replace("=","");
  235.     String completejwt = headerAndPayload + "." + sig;
  236.     mbedtls_ctr_drbg_free( &ctr_drbg );
  237.     mbedtls_entropy_free( &entropy );
  238.     mbedtls_pk_free(&pk_context);
  239.     free(oBuf);
  240.     return completejwt;
  241. }
  242.  
  243. void setup() {
  244.   Serial.begin(115200);
  245.   WiFi.mode(WIFI_STA);
  246.   WiFi.hostname(DEVICE_NAME);
  247.   WiFi.begin(SSID, WIFIPASSWORD);
  248.   WiFi.setAutoReconnect(true);
  249.   while (WiFi.waitForConnectResult() != WL_CONNECTED) {
  250.     delay(5000);
  251.     ESP.restart();
  252.   }
  253. }
  254.  
  255. void loop() {
  256.   String token = createJWT();
  257.   Serial.println(token);
  258.   bool verified = verifyJWT(token);
  259.   Serial.println(verified);
  260.   delay(5000);
  261. }
  262.  
Add Comment
Please, Sign In to add comment