Skip to content

Instantly share code, notes, and snippets.

@gromgit
Created May 30, 2018 05:51
Show Gist options
  • Save gromgit/8b08a15a92e1e5a613ea6fbd161afa9c to your computer and use it in GitHub Desktop.
Save gromgit/8b08a15a92e1e5a613ea6fbd161afa9c to your computer and use it in GitHub Desktop.
Dump salt and digest of bcrypt hash
// Original src: https://github.com/pyca/bcrypt/blob/master/src/_csrc/bcrypt.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
// Maps to character set "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
static const u_int8_t index_64[128] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
255, 255, 255, 255, 255, 255, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 255, 255, 255, 255, 255
};
#define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
/*
* read buflen (after decoding) bytes of data from b64data
*/
static int
decode_bcrypt64(u_int8_t *buffer, size_t len, const char *b64data)
{
u_int8_t *bp = buffer;
const u_int8_t *p = b64data;
u_int8_t c1, c2, c3, c4;
while (bp < buffer + len) {
c1 = CHAR64(*p);
/* Invalid data */
if (c1 == 255)
return -1;
c2 = CHAR64(*(p + 1));
if (c2 == 255)
return -1;
*bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
if (bp >= buffer + len)
break;
c3 = CHAR64(*(p + 2));
if (c3 == 255)
return -1;
*bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
if (bp >= buffer + len)
break;
c4 = CHAR64(*(p + 3));
if (c4 == 255)
return -1;
*bp++ = ((c3 & 0x03) << 6) | c4;
p += 4;
}
return 0;
}
/*
* print len bytes in dex
*/
void
printh(char *h, int len) {
for (int i=0; i<len; i++) {
printf("%02x", (unsigned char)h[i]);
}
}
int main(int argc, char *argv[]) {
char buf[1024];
for (int i=1; i<argc; i++) {
printf("===== %s =====\n", argv[i]);
if (strlen(argv[i]) != 53) {
printf("ERROR: Not a valid bcrypt hash\n");
} else {
memset(buf, '\0', 1024);
// First get the salt (128-bit)
decode_bcrypt64(buf, 22, argv[i]);
// Then the digest (192-bit)
decode_bcrypt64(buf+16, 31, argv[i]+22);
// Dump the results
printf("Salt : ");
printh(buf, 16);
printf("\nDigest: ");
printh(buf+16, 24);
printf("\n");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment