Last active
August 31, 2018 23:21
-
-
Save toolboc/2ab5e578c43e61895d60c90215532847 to your computer and use it in GitHub Desktop.
SAS token generation in C; compile with `gcc -o sas sas.c -lm -lssl -lcrypto`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <openssl/bio.h> | |
#include <openssl/evp.h> | |
#include <openssl/hmac.h> | |
#include <openssl/crypto.h> | |
#include <time.h> | |
#include <string.h> | |
#include <openssl/buffer.h> | |
#include <stdint.h> | |
#include <ctype.h> | |
#include <math.h> | |
/* | |
SAS token generation in C; compile with `gcc -o sas sas.c -lm -lssl -lcrypto` | |
*/ | |
size_t calcDecodeLength(const char* b64input) { | |
size_t len = strlen(b64input), | |
padding = 0; | |
if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are = | |
padding = 2; | |
else if (b64input[len-1] == '=') //last char is = | |
padding = 1; | |
return (len*3)/4 - padding; | |
} | |
int Base64Decode(char* b64message, unsigned char** buffer, size_t* length) { | |
BIO *bio, *b64; | |
int decodeLen = calcDecodeLength(b64message); | |
*buffer = (unsigned char*)malloc(decodeLen + 1); | |
(*buffer)[decodeLen] = '\0'; | |
bio = BIO_new_mem_buf(b64message, -1); | |
b64 = BIO_new(BIO_f_base64()); | |
bio = BIO_push(b64, bio); | |
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer | |
*length = BIO_read(bio, *buffer, strlen(b64message)); | |
// BIO_free_all(bio); | |
return (0); | |
} | |
int Base64Encode2(const char* message, char** buffer) { | |
BIO *bio, *b64; | |
FILE* stream; | |
int encodedSize = 4*ceil((double)strlen(message)/3); | |
*buffer = (char *)malloc(encodedSize+1); | |
stream = fmemopen(*buffer, encodedSize+1, "w"); | |
b64 = BIO_new(BIO_f_base64()); | |
bio = BIO_new_fp(stream, BIO_NOCLOSE); | |
bio = BIO_push(b64, bio); | |
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line | |
BIO_write(bio, message, strlen(message)); | |
BIO_flush(bio); | |
BIO_free_all(bio); | |
fclose(stream); | |
return (0); //success | |
} | |
char rfc3986[256] = {0}; | |
char html5[256] = {0}; | |
void encode(char *s, char *enc, char *tb) | |
{ | |
for (; *s; s++) { | |
if (tb[*s]) sprintf(enc, "%c", tb[*s]); | |
else sprintf(enc, "%%%02X", *s); | |
while (*++enc); | |
} | |
} | |
int urlEncode(char *enc, char *url) | |
{ | |
int i; | |
for (i = 0; i < 256; i++) { | |
rfc3986[i] = isalnum(i)||i == '~'||i == '-'||i == '.'||i == '_' | |
? i : 0; | |
html5[i] = isalnum(i)||i == '*'||i == '-'||i == '.'||i == '_' | |
? i : (i == ' ') ? '+' : 0; | |
} | |
encode(url, enc, rfc3986); | |
return 0; | |
} | |
void main() { | |
char uri[] = "tiara.azure-devices.net/devices/devicePaho"; | |
char encodedUri[(strlen(uri) * 3) +1]; | |
urlEncode(encodedUri, uri); | |
printf("encodeduri: %s\n", encodedUri); | |
unsigned char key[] = "K1VrD7A8YdWWzH8Q3krGztNAmUODB1GUqJ76WOIdA9Q="; | |
size_t keyLen; | |
unsigned char *decodedKey; | |
Base64Decode(key, &decodedKey, &keyLen); | |
printf("decoded key: "); | |
int i; | |
for(i = 0; i < keyLen; i++) printf("%02x", decodedKey[i]); | |
int toSignLen = strlen(encodedUri) + 12; | |
unsigned char toSign[toSignLen]; | |
int expiry = 1546300800; | |
printf("\ntimestamp: %d\n", expiry); | |
snprintf(toSign, toSignLen, "%s\n%d", encodedUri, expiry); | |
printf("toSign: %s\n", toSign); | |
unsigned char* result; | |
unsigned int resultLen = 32; | |
result = (unsigned char*) malloc(sizeof(char) * resultLen); | |
result = HMAC(EVP_sha256(), decodedKey, strlen(decodedKey), toSign, strlen(toSign), NULL, NULL); | |
printf("sig: "); | |
for(i = 0; i < resultLen; i++) printf("%02x", result[i]); | |
char* base64EncodeOutput; | |
Base64Encode2(result, &base64EncodeOutput); | |
printf("\nb64: %s\n", base64EncodeOutput); | |
char enc[(strlen(base64EncodeOutput) * 3) + 1]; | |
urlEncode(enc, base64EncodeOutput); | |
char token[256]; | |
snprintf(token, sizeof(token), "SharedAccessSignature sr=%s&sig=%s&se=%d", encodedUri, enc, expiry); | |
printf("final signature: %s\n", token); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment