#include #include #include #include #include #define CDKEY_LENGTH 23 #define CDKEY_SIGNED_PART 17 static unsigned char CDKEY_SECRET[] = {0x4d,0x67,0xde,0xb9,0x60,0xce,0x38,0x30,0xe1,0xb7,0x40,0xe5,0xeb,0x39,0xe0,0x15}; static bool is_hex_digit(int c) { return c >= '0' && c <= '9' || c >= 'A' && c <= 'Z'; } static char *hexlify(const unsigned char *data, size_t len) { char *res = malloc(len * 2 + 1); for (size_t i = 0; i < len; i++) { sprintf(&res[i*2], "%02X", (unsigned) data[i]); } return res; } __attribute__((noinline)) static bool validate_cdkey(const char *cdkey) { if (strlen(cdkey) != CDKEY_LENGTH) { return false; } for (int i = 0; i < strlen(cdkey); i++) { switch (i) { case 5: case 11: case 17: if (cdkey[i] != '-') return false; break; default: if (!is_hex_digit(cdkey[i])) return false; break; } } MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, cdkey, CDKEY_SIGNED_PART); MD5_Update(&ctx, CDKEY_SECRET, sizeof(CDKEY_SECRET)); static unsigned char digest[MD5_DIGEST_LENGTH]; MD5_Final(digest, &ctx); char *hex_digest = hexlify(digest, sizeof(digest)); for (int i = CDKEY_SIGNED_PART+1, j = 0; i < CDKEY_LENGTH; i++, j++) { if (cdkey[i] != hex_digest[j]) { free(hex_digest); return false; } } free(hex_digest); return true; } int main(void) { FILE *f = fopen("./cd-key.txt", "r"); if (!f) { fprintf(stderr, "failed to open CD key file\n"); return 1; } char cdkey[CDKEY_LENGTH+2]; if (!fgets(cdkey, sizeof(cdkey), f)) { fprintf(stderr, "failed to read CD key file\n"); return 1; } if (strlen(cdkey) > 0 && cdkey[strlen(cdkey)-1] == '\n') { cdkey[strlen(cdkey)-1] = '\0'; } if (!validate_cdkey(cdkey)) { fprintf(stderr, "invalid cdkey\n"); return 1; } fprintf(stderr, "Good job!\n"); return 0; }