Edgar, et. al., I am attaching two things: 1) The key file I am trying to decrypt.
Filename: export-key.pw-is-foo.nc This is the Windows-produced file that I need to decrypt. The passphrase I used to extract this file using netsh was "foo". 2) The code that I am currently using to try and decrypt the extracted key. Filename: oSSL_key_dx.c This is the OpenSSL-based decryption code I have written. It's fairly brute-force. I have added several comments to indicate where it is I am having trouble. Send questions and suggestions. I will try whatever you suggest when I return home after the MS Plugfest. Thanks. Chris -)-----
export-key.pw-is-foo.nc
Description: Cdf file
/* ========================================================================== ** * oSSL_key_dx.c * * $Id$ * * -------------------------------------------------------------------------- ** * * Description: * Decrypt an exported BranchCache Server Secret key. * * -------------------------------------------------------------------------- ** * * Notes: * + To compile: cc -o oSSL_key_dx oSSL_key_dx.c -lssl * * + These are the steps needed to extract an exported PeerDist key: * 1) Generate SHA256( passphrase ). * 2) AES Decrypt the contents of the keyfile, using SHA256( passphrase ) * as the key. * 3) Separate the first 32 bytes of the result of step 2 from the * remainder. The remainder is is the server's secret key. * The first 32 bytes is the SHA256 of the key. * 4) Validate the key against the SHA256 of the key. * * ========================================================================== ** */ #include <stdlib.h> /* Standard library. */ #include <stdio.h> /* I/O stuff. */ #include <errno.h> /* For <errno>. */ #include <string.h> /* for strerror(3). */ #include <stdarg.h> /* Variable arg lists.*/ #include <openssl/aes.h> /* OpenSSL AES tools. */ #include <openssl/sha.h> /* OpenSSL sha tools. */ /* -------------------------------------------------------------------------- ** * Macros: * * Err() - This is a conceited little macro that simply replaces * fprintf( stderr, ... ) with something shorter and easier * to type. * Say() - This is a conceited little macro that simply replaces * printf(3) with something shorter and easier to type. * ErrStr - Shorthand for the error message associated with <errno>. */ #define Err( ... ) (void)fprintf( stderr, __VA_ARGS__ ) #define Say( ... ) (void)printf( __VA_ARGS__ ) #define ErrStr (strerror( errno )) /* -------------------------------------------------------------------------- ** * Defined constants: */ #define bSIZE 2048 /* -------------------------------------------------------------------------- ** * Static Functions: */ void Fail( char *fmt, ... ) /* ------------------------------------------------------------------------ ** * Format and print a failure message on <stderr>, then exit the process. * * Input: fmt - Format string, as used in printf(), etc. * ... - Variable parameter list. * * Output: none * * Notes: Exits the process returning EXIT_FAILURE. * * ------------------------------------------------------------------------ ** */ { va_list ap; va_start( ap, fmt ); (void)fprintf( stderr, "Failure: " ); (void)vfprintf( stderr, fmt, ap ); va_end( ap ); exit( EXIT_FAILURE ); } /* Fail */ static void hexlist( FILE *outF, const unsigned char *bufr, int len ) /* ------------------------------------------------------------------------ ** * Output a hex string representing a block of bytes. * * Input: outF - Stream to which to send the output. * bufr - A pointer to a bunch of bytes. * len - Number of bytes of <bufr> to output. * * Output: <none> * * ------------------------------------------------------------------------ ** */ { int i; (void)fprintf( outF, "[" ); for( i = 0; i < len; i++ ) { (void)fprintf( outF, "%.2x", bufr[i] ); } (void)fprintf( outF, "]" ); } /* hexlist */ /* -------------------------------------------------------------------------- ** * Program Mainline. */ int main( int argc, char *argv[] ) /* ------------------------------------------------------------------------ ** * Program Mainline. * * Input: argc - You know what this is. * argv - You know what to do. * * Output: EXIT_SUCCESS * or, if you are having a really bad day, EXIT_FAILURE. * * ------------------------------------------------------------------------ ** */ { int i; FILE *keyf; unsigned char *doublewide; AES_KEY aes_ppHash[1]; size_t readlen; size_t phraselen; unsigned char inBufr[bSIZE]; unsigned char outBufr[bSIZE]; unsigned char ppHash[SHA256_DIGEST_LENGTH]; unsigned char iv[32]; /* Validate the command line. Somewhat. */ if( argc != 3 ) { Err( "Usage:\t%s <keyfile> <passphrase>\n", argv[0] ); Err( "\tWhere <keyfile> is the name of the file that contains the\n" ); Err( "\texported key, and <passphrase> is the phrase used as the\n" ); Err( "\tencryption key when the server secret was exported.\n\tIt " ); Err( "may be necessary to place the passphrase in quotation marks.\n" ); exit( EXIT_FAILURE ); } /* Open the keyfile. */ keyf = fopen( argv[1], "r" ); if( NULL == keyf ) { Err( "Failure opening file \"%s\"; %s.\n", argv[1], ErrStr ); return( EXIT_FAILURE ); } /* Read the keyfile. * FIX: This assumes that the encrypted file fits into one buffer. */ readlen = fread( inBufr, 1, bSIZE, keyf ); if( 0 == readlen ) { Err( "Error reading input from %s; %s.\n", argv[1], ErrStr ); return( EXIT_FAILURE ); } Err( "Read %d bytes from file %s.\n", readlen, argv[1] ); /* Expand and hash the passphrase. * NOTE: This "emulates" Windows Unicode encoding. */ phraselen = strlen( argv[2] ); doublewide = (unsigned char *)calloc( phraselen, 1 ); for( i = 0; i < phraselen; i++ ) { doublewide[i*2] = argv[2][i]; doublewide[1+(i*2)] = '\0'; } Err( "PassPhrase: " ); hexlist( stderr, doublewide, 2*phraselen ); Err( "\n" ); (void)SHA256( outBufr, (phraselen * 2), ppHash ); free( doublewide ); /* Initializes the AES_KEY with the key and the 256-bit size. * Note: 256 == key size (32 bytes) in bits. * This initializes the <aes_ppHash> variable. */ (void)AES_set_decrypt_key( ppHash, 256, aes_ppHash ); /* We don't know how to handle the <iv>, so we clear it. * Then try to cbc decrypt the input, writing to the output. * Note: Yes, we call AES_cbc_encrypt() to decrypt the data. * FIX: This is probabably wrong. We never specify the CBC block size, * only the key size. The default appears to be 32 bytes, just * like the key size (and the iv size). */ memset( iv, 0, 32 ); AES_cbc_encrypt( inBufr, outBufr, readlen, aes_ppHash, iv, AES_DECRYPT ); /* Output the results. * 1) The decrypted key. * 2) The decrypted hash. * 3) The hash calculated from the decrypted key. */ Say( " Key: " ); hexlist( stdout, &outBufr[32], readlen-32 ); Say( "\n Hash: " ); hexlist( stdout, outBufr, 32 ); Say( "\nKey hash: " ); (void)SHA256( &outBufr[32], readlen-32, ppHash ); hexlist( stdout, ppHash, 32 ); Say( "\n" ); return( EXIT_SUCCESS ); } /* main */ /* ========================================================================== */
_______________________________________________ cifs-protocol mailing list cifs-protocol@cifs.org https://lists.samba.org/mailman/listinfo/cifs-protocol