# OpenSSL DES encryption for KCV calculation

I'm trying to implement a simple command-line tool to calculate the (Key Check Value) KCV of some encryption keys. The algorithm for the KCV is simply to encrypt a block of 8 zeros with DES and get the first three bytes of it (this is called VISA KCV, and there are a bunch of other KCV algorithms).

So, I wrote this code:

/*----------------------------------------------------------------------------*/
static void
str2DES_cblock_(const char *str, DES_cblock* out)
{
// Make a char pointer and point it at the start of the array
unsigned char *o;
o = out[0];
// Read the string
int i;
for (i = 0; i < 8; i++)
sscanf(&(str[i*2]),"%2hhx", o++);
}

static int
getVisaKcv_( const char* key, const int keyStrLen, unsigned char* kcv )
{
DES_cblock key1, key2;
DES_key_schedule keySchedule1, keySchedule2;
DES_cblock encryptedBlock;

int rc = EXIT_SUCCESS;

static const_DES_cblock blockToEncrypt_ = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

memset( encryptedBlock, 0x00, sizeof(encryptedBlock) );

if( 16 == keyStrLen )
{
str2DES_cblock_( key, &key1 );
DES_set_key_unchecked( &key1, &keySchedule1 );
DES_ecb_encrypt(
&blockToEncrypt_,
&encryptedBlock,
&keySchedule1,
DES_ENCRYPT
);

kcv[0] = encryptedBlock[0];
kcv[1] = encryptedBlock[1];
kcv[2] = encryptedBlock[2];

}
else if( 32 == keyStrLen )
{
str2DES_cblock_( key,    &key1 );
str2DES_cblock_( key+16, &key2 );

DES_set_key_unchecked( &key1, &keySchedule1 );
DES_set_key_unchecked( &key2, &keySchedule2 );

DES_ecb2_encrypt(   &blockToEncrypt_,
&encryptedBlock,
&keySchedule1,
&keySchedule2,
DES_ENCRYPT );

kcv[0] = encryptedBlock[0];
kcv[1] = encryptedBlock[1];
kcv[2] = encryptedBlock[2];
}
else
{
rc = ERROR_INVALID_PARAM;
}

return rc;
}


It uses OpenSSL's functions to perform encryption. The things is that it is giving me wrong results. For exemple, encrypting "19c7221b33c1b2b4c68bc48deb86234b" results in encryptedBlock = [ 33 4D 78 7E FB C0 ED E8 ]. Some high quality validation tools I have (it is called BP-Tools and works for all things payment-industry related) gives encryptedBlock = [ 90 D4 49 08 A7 9F 45 44 ] as result. I'm not sure where the problem is (it is a very simple encryption). Did I forget something in the sequence of OpenSSL API calls? It gives wrong results for 8-byte keys also.

Here are some test cases (they match both EFTLab's and BP-Tools results):

Enc( plaintext=[0000000000000000], key=[9be8ec942f9f7791]                   )   = [F4E94D2A2901D6C6]
Enc( plaintext=[0000000000000000], key=[6afbadf94fd06945d365856382898c25]   )   = [F65EC8B0B78F2C0A]
Enc( plaintext=[0000000000000000], key=[8f40053aae44e017]                   )   = [4A83D7F98644363E]
Enc( plaintext=[0000000000000000], key=[19c7221b33c1b2b4c68bc48deb86234b]   )   = [90D44908A79F4544]
Enc( plaintext=[0000000000000000], key=[b0e9c35e20171642]                   )   = [7FBA49A7CD6A8AEB]
Enc( plaintext=[0000000000000000], key=[a12815befca06412f357db3ab41d7cf9]   )   = [67F735CD1696E114]
Enc( plaintext=[0000000000000000], key=[e5c82dbe8c0b3c17]                   )   = [4CACBD023C95FD7C]
Enc( plaintext=[0000000000000000], key=[c74b48ebfa79f8ca46d06f8436597230]   )   = [7FD3FA9F5B338E13]

• This is not a crypto question. You don't show str2DES_cblock_ but it must be wrong, because if I add a correct one your code exactly as posted works. It does give compile warnings (which you should always check) because you omitted the & on the first two args to des_ecb2_encrypt and thus pass pointers of the wrong type; the C standard allows these to be different and cause Undefined Behavior, but in practice on all systems 'normal' programmers use today all data pointers are the same. – dave_thompson_085 Mar 11 at 9:55
• Actually I wrote str2DES_cblock because I can't get DES_string_to_key to work properly. Anyway it is a valid point and I will update the question. Thank you. – daniel.franzini Mar 11 at 16:59
• Your modified code works for me, with no change beyond adding main(). Check that you're actually running the code you posted -- if you use an IDE, or a source and/or build management system or tools, make sure you don't have a stale or wrong version someplace. – dave_thompson_085 Mar 12 at 3:32