[cifs-protocol] FW: [REG:111061756137964] Encryption of the key for "netsh branchcache importkey and exportkey.
Christopher R. Hertel
crh at ubiqx.mn.org
Fri Jun 24 18:52:00 MDT 2011
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 -)-----
-------------- next part --------------
A non-text attachment was scrubbed...
Name: export-key.pw-is-foo.nc
Type: application/x-netcdf
Size: 80 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/cifs-protocol/attachments/20110624/d6176d93/attachment.nc>
-------------- next part --------------
/* ========================================================================== **
* 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 */
/* ========================================================================== */
More information about the cifs-protocol
mailing list