ISO 9797 algorithm 3
Last Friday I set out to implement ISO 9797 algorithm 3 using the OpenSSL library. I did not have the specification handy, so I decided to to the best I could with what I could find by way of examples on the net.
I came across a description of the algorithm in this 2005 thread (http://www.derkeiler.com/Newsgroups/sci.crypt/2005-02/0374.html). This was posted in a query by someone named Christian. He also posted his keys, data and the expected answer.
Francois Grieu replied with, "This is very likely ISO/IEC 9797-1, using DES as the block cipher,
padding method 2, MAC algorithm 3." He provided an answer by sharing sample code in "some near-extinct dialect".
I've implemented the same in c for the purpose of research.
I came across a description of the algorithm in this 2005 thread (http://www.derkeiler.com/Newsgroups/sci.crypt/2005-02/0374.html). This was posted in a query by someone named Christian. He also posted his keys, data and the expected answer.
H0 = 0
stages 1 to n: Hj = Enc(K, Dj XOR H{j-1})
MAC = Enc(K, Dec(K', Hn))
Francois Grieu replied with, "This is very likely ISO/IEC 9797-1, using DES as the block cipher,
padding method 2, MAC algorithm 3." He provided an answer by sharing sample code in "some near-extinct dialect".
set m0 72C29C2371CC9BDB #message
set m1 65B779B8E8D37B29
set m2 ECC154AA56A8799F
set m3 AE2F498F76ED92F2
set pd 8000000000000000 #padding
set iv 0000000000000000 #initialisation vector
set k0 7962D9ECE03D1ACD #key
set k1 4C76089DCE131543
set xx {iv} # setup
for mj in {m0} {m1} {m2} {m3} {pd} # for each block including padding
set xx `xor {xx} {mj}` # chain
set xx `des -k {k0} -c {xx}` #encrypt
end
set xx `des -k {k1} -d {xx}` #decrypt
set xx `des -k {k0} -c {xx}` #encrypt
echo {xx} #show result
5F1448EEA8AD90A7
I've implemented the same in c for the purpose of research.
#include openssl/des.h
#include memory
#include string.h
//message + padding
const unsigned char msg[40] = { 0x72, 0xC2, 0x9C, 0x23, 0x71, 0xCC, 0x9B, 0xDB,
0x65, 0xB7, 0x79, 0xB8, 0xE8, 0xD3, 0x7B, 0x29,
0xEC, 0xC1, 0x54, 0xAA, 0x56, 0xA8, 0x79, 0x9F,
0xAE, 0x2F, 0x49, 0x8F, 0x76, 0xED, 0x92, 0xF2,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//initialization vector
unsigned char iv[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned char k0[8] = { 0x79, 0x62, 0xD9, 0xEC, 0xE0, 0x3D, 0x1A, 0xCD };
unsigned char k1[8] = { 0x4C, 0x76, 0x08, 0x9D, 0xCE, 0x13, 0x15, 0x43 };
void print_hex(const unsigned char *bs, int n) {
for (int i = 0; i < n; i++)
printf("%02x", bs[i]);
printf("\n");
}
void des_ecb_crypt(unsigned char* input, unsigned char* output, int encrypt, unsigned char* key) {
des_key_schedule sched;
des_set_key((des_cblock *) key, sched);
DES_ecb_encrypt((const_DES_cblock *)input,
(const_DES_cblock *)output,
&sched,
encrypt);
}
void xor_block(unsigned char* src, unsigned char* dest) {
for (int x = 0; x < 8; x++) {
src[x] = src[x] ^ dest[x];
}
}
int main(int argc, char* argv[]) {
unsigned char output[8];
unsigned char xx[8];
unsigned char block[8];
int offset = 0;
memcpy(xx, iv, 8);
// Chain and encrypt 5 8-bit blocks
for (int x = 0; x < 5; x++) {
memcpy(block, &msg[offset] , 8);
offset+=8;
//set xx `xor {xx} {mj}` # chain
xor_block(xx, block);
//set xx `des -k {k0} -c {xx}` #encrypt
des_ecb_crypt(xx, output, DES_ENCRYPT, k0);
memcpy(xx, output, 8);
}
des_ecb_crypt(xx, output, DES_DECRYPT, k1);
memcpy(xx, output, 8);
des_ecb_crypt(xx, output, DES_ENCRYPT, k0);
memcpy(xx, output, 8);
print_hex(xx, 8);
return 1;
}
Comments