MAC variant of MSR DUKPT? - encryption

Currently I am working on a ChipCard EMV device decryption. Down below is the related data I have after using the transaction (TLV format as Tag Length Value):
<DFDF54> --- It means KSN
0A
950003000005282005B4
<DFDF59>---- per instruction, it is called Encrypted Data Primative
82 ---- length of value in hex, when more than 255 degits, use 82
00D815F35E7846BF4F34E56D7A42E9D24A59CDDF8C3D565CD3D42A341D4AD84B0B7DBFC02DE72A57770D4F795FAB2CE3A1F253F22E0A8BA8E36FA3EA38EE8C95FEBA3767CDE0D3FBB6741A47BE6734046B8CBFB6044C6EE5F98C9DABCD47BC3FD371F777E7E1DCFA16EE5718FKLIOE51A749C7ECC736CB7780AC39DE062DAACC318219E9AAA26E3C2CE28B82C8D22178DA9CCAE6BBA20AC79AB985FF13611FE80E26C34D27E674C63CAC1933E3F9B1BE319A5D12D16561C334F931A5E619243AF398D9636B0A8DC2ED5C6D1C7C795C00D083C08953BC8679C60
I know BDK for this device is 0123456789ABCDEFFEDCBA9876543210. Per decryption instruction, it mentioned that DFDF59 contains the following tags:
FC<len>/* container for encrypted generic data */
F2<len>/*container for Batch Data*/
... /*Batch Data tags*/
F3<len>/*container for Reversal Data, if any*/
... /*Reversal Data tags*/
Per instruction, it mentioned "MAC variant of MSR DUKPT", where MAC stands for message authentication code, and "Parse the data through TLV format. For encrypted data tag, use TDES_Decrypt_CBC to decrypt it".
I tried to use 3DES DUKPT using KSN, BDK, and encrypted data DFDF59. It wouldn't work. Can anyone in decryption field give me some advice? Our vendor is very reluctant to share their knowledge ...
I have no idea how MAC is really playing a role here in decryption.... I thought MAC is just an integrity check.... I am using session key for 3DES DUKPT that was generated from KSN and BDK. this works for other decryptions in this device, but doesn't solve the DFDF59 (chip card EMV decryption).... That is why I start to wonder whether I am using the right session key or not.... Feel free to just throw ideas out there. Thank you!

If you look closely at DUKPT internals it generates a transaction key out of the current future keys and encryption counter. This 'transaction key' for a specific KSN has several variants (which effectively are just xor masks that you put on the transaction key to differentiate it for PIN, MAC req, MAC rsp, data encryption req and rsp usages). These variants mean that you use a different key to generate PIN and different key to encrypt data (so that you cannot ie. decrypt/attack PINblock when able to select data buffer arbitrarily). Using MAC variant means only that for the encryption operation you will be using a certain mask for the DUKPT transaction key.

Related

I need an alternative to initialization vector encryption

I helped a small non-profit create a cool "anonymous" help line where their clientele can send in SMS questions to a phone number and organization can respond without knowing who the client is. It's proven to be a very helpful tool for the organization. I am in the process of re-writing it from scratch and am looking for advice on how to handle the anonymity aspect of it.
The way that v1 works is by simply encrypting / decrypting the client phone number and using that as the client id in the data model using 'aes-256-ctr'. Since the staff / leadership of the nonprofit do not have access to the encryption key, they can legitimately claim to not be able to have access to any p.i.i. not disclosed voluntary by their clients. When they issue a message response to the client, I simply need to decrypt the client id to get the phone that I need in order to dispatch the message.
v1 encrpytion strategy:
export const encrypt = (text) => {
const cipher = crypto.createCipher(algorithm, password);
let crypted = cipher.update(text, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
};
export const decrypt = (text) => {
const decipher = crypto.createDecipher(algorithm, password);
let dec = decipher.update(text, 'hex', 'utf8');
dec += decipher.final('utf8');
return dec;
};
Lately though, I've been getting console warnings because new node versions will output a warning when using createCipher instead of createCipheriv to utilize initialization vector. On my v2 rewrite I switched it over to createCipheriv, but that has the effect of "randomizing" the encryption output and breaking my ability to rely upon the encrypted phone number as a reliable, consistent client id. Being able to reliably group client messages is an important requirement to provide a conversational view in the UX.
How might I properly encrypt the identifying phone number such that only I can decrypt it at message send time and still have some kind of consistent internal ID by which to group messages? I don't HAVE to rely upon the encrypted phone number as the client id, but I can't think of any reliable alternative (via a lookup table of some kind). If possible I don't want to fall back on createCipher without the I.V. if its not a best practice.
I should note that this application is not dealing with any legally sensitive information or anything high stakes like that. I probably could get away with storing the unencrypted phone number in the database and just not exposing it to the front end and maintain anonymity, I just really don't like that idea if there is a sensible workaround.
Any ideas?
You should be generating a new random (or UUID-style) client id for each new client. The benefit of this is that you can keep using a secure encryption method and still identify and lookup users quickly.
If you want the phone number field to act as a unique lookup, simply take an HMAC of the phone number and use that for lookups (as well as storing encrypted) - it can't ever be decrypted and is guaranteed to be consistent across invocations for the same phone number under a given key.
EDIT: To migrate existing data, you should, for each record, take the client_id (currently the encrypted phone number), decrypt it, HMAC it, and store the result in a new column. Then, generate a new ID and set that to be the client_id. This allows lookup by actual client_id and by phone number.

How to use Encryption in SAP

SAP servers are capable of encrypting and hashing data. But there doesn't appear to be a suitable API to call. SAP Note 1456433 talks about the class CL_SEC_SXML_XENCRYPTION. The signature of basic encryption is clearly geared towards SSF and unsuitable to basic private key encryption/decryption. I don't want/need envelopes and user certificates. Just private keys.
I found an AES library on GitHub AES library in ABAP and tweaked that to suit us. But it is very slow. I would like to use the encryption libraries SAP has. Clearly, the libraries are there but find a suitably exposed API seems the issue.
Does anybody know how to use basic encryption in SAP?
In SAP ABAP stack, using ABAP.
Eg (a call to use AES-CBC 128, with PKCS7 padding
where only a private key and data to encrypt is required. As example:
public static method encrypt_xstring
importing i_key type xstring
i_data type xstring
i_initialization_vector type xstring optional
i_padding_standard type char10 optional
i_encryption_mode type char10 optional
exporting e_data type xstring
Use case is encrypting data on clients with a private key and sending the data to SAP system. The source supports private keys and libraries like AES-CBC.
And we have encrypted data interchange working.
Next step is to use a supported and faster library.
EDIT: In case anyone needs to encryption / decryption properly in abap
And is looking at the answer. Use class CL_SEC_SXML_WRITER.
CL_SEC_SXML_WRITER was exactly what i was looking for
BUT SAP didnt expose it properly. It is only useful for encryption no decryption.
When interacting with external libraries. Where PKCS7 padding is used and SALTs
or Initialization vectors are required.
SAP offer an ENCRYPT_IV but no Decrypt_IV. Why ????
So you cant use the tool and remain compliant. :(
It is not considered safe to use AES-CBC without IV.
Why would SAP do that ?
ENCRYPT_IV instead of ENCRYPT but no DECRYPT_IV
The offer an Add Padding but no remove padding. OK roll your own padding removal, no big deal. Its like the must be another library for the other direction.
So i can use the tool to encrypt but not decrypt.
My main problem was decrypting quickly strings sent from a mobile device.
So still need to use the old ABAP code for that :(
I have similar requirements and I found the cl_sec_sxml_writer class. Please have a look at the following example. Note that the writer requires XSTRING parameters which is why I'm using conversion classes.
REPORT zged_aes.
DATA lv_message_string TYPE string.
" create message
DATA(lr_conv_sec) = cl_abap_conv_out_ce=>create( ).
lr_conv_sec->write( data = 'This is my secret' ).
" create key
DATA(lr_conv_key) = cl_abap_conv_out_ce=>create( ).
lr_conv_key->write( data = 'MySymmetricKey' ).
" encrypt using AES256
cl_sec_sxml_writer=>encrypt(
EXPORTING
plaintext = lr_conv_sec->get_buffer( )
key = lr_conv_key->get_buffer( )
algorithm = cl_sec_sxml_writer=>co_aes256_algorithm_pem
IMPORTING
ciphertext = DATA(lv_message) ).
" decrypt message
cl_sec_sxml_writer=>decrypt(
EXPORTING
ciphertext = lv_message
key = lr_conv_key->get_buffer( )
algorithm = cl_sec_sxml_writer=>co_aes256_algorithm_pem
IMPORTING
plaintext = DATA(lv_message_decrypted) ).
" convert xstring to string for output
cl_abap_conv_in_ce=>create( input = lv_message_decrypted)->read( IMPORTING data = lv_message_string ).
" output secret message
WRITE lv_message_string.
I tested it on a NetWeaver 7.50 SP 6 system.
I got the ENCRYPT_IV method to work alongside method DECRYPT of class CL_SEC_SXML_WRITER.
The caveat here is that I didn't generate the Symmetric Key and IV by making use of Class cl_abap_conv_out_ce.
I already had my keys and IV from a Java implementation test.
The only thing I needed was to create the Key and IV as an XSTRING and initializing them with the Hex format of my Java implementation (they were in Byte format.
Because of this, I first converted them to Hex and passed those values to the ABAP Xstring types).

3DES-DUKPT (CBC) decryption confirmation

I have Key Serial Number (KSN), Base Derivation Key (BDK), and encrypted string.
KSN = 9500030000044520002B
BDK = 0123456789ABCDEFFEDCBA9876543210
Encrypted string
23F87C010DCD08E0211D509F3310B1A63564D44134A512AA0740CA2A0FD81BF045AF70395C537774680B566548C2966DFD7F575CC756408A89BCF12A93B8873114FF6EFC69014EA0E0A4EBD392EF40A3F1E15012B3D613E18E4CFD4DE3AFCD771D8B2CE8AB54B1CB7671F24F8562262AAA603C45BF87DE33407234927D7CDA28C86CE29E05A9D03ED65EB3D5DDD3C15A61A79AB8CB7481828339A0B099EDC3BBE3A1C416A06E965FF3CAF2CC395E691AB86C325183EF3A245A3DDF53CBD6D6AEFD0769F560165E4B5C99EBA2584AD3EC
The decryption from the Device Manufacturer Menu is supposed to be:
Right answer
FC8200C6F28200C282027C008E1200000000000000004201410342035E031F005F24031912315F25039507019F0607A00000000310109F0702FFC09F0D0500000000009F0E0500000000009F0F0500000000009F100706010A039600009F2608738091EC178FF5709F2701409F36020017950508001410009B02E8009C01009F3303E0F8C89F34034203009F370450577DCF9F40057000B0B001DFDF70050000000000DFDF71050000000000DFDF7205000000000057134761739981010014D19122010123456789012F000000000000
My decryption turned out to be:
E4771F740C1B1D45DFA193A1DF73C80B3CF68F625DB4604A4C5C392B72BDC98236FAA09D32D674A45D7C3AFAA08E26DAD0B3ABC14662F9D386B9C2F7B992EC35BD7B765450C9E8E56D5D1CEAAE0641E5CB66D2102C58A6325C845E62BBB8994E0441AF1887CDD0C3C0AD2A8AD178A949C0944D46A04DA08DAE30FA571CE4C0EACE4AAFC503708AD0240584C80506F98F0C8D8E348F0A5B0E949EED814C8F1C2B9157B66455715685673D0F1B816AD4AEF7743EB9E339361A733F1EF37CA1DC5D468CA988DDD9E74E7CCC9F999FDBBCFE
and session key turned out to be:
7ED0EDD8A1961ABF7CFC995219B80FC57ED0EDD8A1961ABF
Can any decryption professional run a little 3DES-DUKPT and check it for me?
The instruction from the Device manufacturer claims that 3DES-DUKPT is formed, using Data Skye variant and (KSN)" for the encrypted value.
THank you!
I recommend using the BP-Tools freeware to check your results.
It contains a DUKPT calculator.

TCL code that can encrypt and decrypt a string

I need a piece of code that defines functions which can encrypt and decrypt a piece of string. What I basically want is that the string should not be visible to third-party users, so that when the string originates in one file, it is converted to, say, an integer value using the encrypt function and then it is passed as parameter to another file. There the decrpyt function then decrypts it back and uses the string to perform actions on it.
Any suggestions or already available codes will be just fine!
Please help me out. Thanks!
Install tcllib. There are several standard encryption algorithms implemented in tcllib.
The following encryption algorithms are available:
blowfish: http://tcllib.sourceforge.net/doc/blowfish.html
aes: http://tcllib.sourceforge.net/doc/aes.html
des (including triple des): http://tcllib.sourceforge.net/doc/des.html
rc4: http://tcllib.sourceforge.net/doc/rc4.html
The des package in Tcllib should do what you want. It's pretty easy to use:
package require des
set key "12345678"; # Must be 8 bytes long
set msg "abcde"
##### ENCRYPTION
set encryptedMsg [DES::des -dir encrypt -key $key $msg]
# $encryptedMsg is a bunch of bytes; you'll want to send this around...
##### DECRYPTION
set decryptedMsg [DES::des -dir decrypt -key $key $encryptedMsg]
puts "I got '$decryptedMsg'"
Note that DES will pad the message out to a multiple of 8 bytes long.
Please visit the TCL/TK homepage e.g
here:http://wiki.tcl.tk/900
That's just one way of doing it. There will be much more, I'm sure.

Decrypting DUKPT Encrypted Track Data

As the title says, I am trying to decrypt DUKPT encrypted track data coming from a DUKPT enabled scanner.
I have the ANSI Standard (X9.24) for DUKPT and have successfully implemented the ability to generate the IPEK from the KSN and BDK. Furthermore, I have successfully implemented the ability to generate the Left and Right MAC Request and Response Keys by XORing the PIN Encryption Keys. Lastly, I am able to generate the EPB.
From here, I don't understand how to generate the MAC Request and Response from the L/R Keys that I have generated.
Lastly, once I get to that step, what comes next? When do I actually have the key that decrypts the track data sent by a DUKPT enabled device?
I am aware of the Thales Simulator and jPOS. My code is currently referencing the Thales Simulator to do all of its work. But, the file decryption process just isn't returning the expected data.
If anybody can offer some insight into decrypting track data, it would be much appreciated.
http://thalessim.codeplex.com/
http://jpos.org/
I spent too much time studying the horrible X9.24 spec and finally got both the encryption and decryption working with my vendor’s examples and marketing promptly decided to switch vendors. Since it is a standard, you would think that anybody’s implementation would be the same. I wish. Anyway, there are variations on how things are implemented. You have to study the fine print to make sure you are working things the same as your other side.
But that is not your question.
First if you need to decrypt a data track from a credit card, you are probably interested in producing a key that will decrypt the data based upon the original super secret Base Derivation Key. That has nothing to do with the MAC generation and is only mentioned in passing in that dreadful spec. You need to generate the IPEK for that key serial number and device ID and repeatedly apply the “Non-reversible Key Generation Process” from the spec if bits are set in the counter part of the full key serial number from the HSM.
That part of my code looks like this: (Sorry for the long listing in a posting.)
/*
* Bit "zero" set (this is a 21 bit register)(ANSI counts from the left)
* This will be used to test each bit of the encryption counter
* to decide when to find another key.
*/
testBit=0x00100000;
/*
* We have to "encrypt" the IPEK repeatedly to find the current key
* (See Section A.3). Each time we encrypt (generate a new key),
* we need to use the all prior bits to the left of the current bit.
* The Spec says we will have a maximum of ten bits set at any time
* so we should not have to generate more than ten keys to find the
* current encryption key.
*/
cumBits=0;
/*
* For each of the 21 possible key bits,
* if it is set, we need to OR that bit into the cumulative bit
* variable and set that as the KSN count and "encrypt" again.
* The encryption we are using the goofy ANSI Key Generation
* subroutine from page 50.
*/
for(int ii=0; ii<21; ii++)
{
if( (keyNumber&testBit) != 0)
{
char ksr[10];
char eightByte[8]={0};
cumBits |= testBit;
ksn.count=cumBits; /* all bits processed to date */
memcpy(ksr, &ksn,10); /* copy bit structure to char array*/
memcpy(crypt,&ksr[2],8); /* copy bytes 2 through 9 */
/*
* Generate the new Key overwriting the old.
* This will apply the "Non-reversible Key Generation Process"
* to the lower 64 bits of the KSN.
*/
keyGen(&key, &crypt, &key);
}
testBit>>=1;
}
Where
keyNumber is the current counter from the ksn
ksn is an 80 bit structure that contains the 80 bit Key Serial Number from the HSM
crypt is a 64 bit block of data I have it of type DES_cblock since I am using openSSL.
key is a 128 bit double DES_cblock structure.
The keyGen routine is almost verbatim from the “Non-reversible Key Generation Process” local subroutine on page 50 of the spec.
At the end of this, the key variable will contain the key that can be used for the decryption, almost. The dudes that wrote the spec added some “variant” behavior to the key to keep us on our toes. If the key is to be used for decrypting a data stream such as a credit card track, you will need to XOR bytes 5 and 13 with 0xFF and Triple DES encrypt the key with itself (ECB mode). My code looks like:
DOUBLE_KEY keyCopy;
char *p;
p=(char*)&key;
p[ 5]^=0xff;
p[13]^=0xff;
keyCopy=key;
des3(&keyCopy, (DES_cblock *)&key.left, &key.left);
des3(&keyCopy, (DES_cblock *)&key.right, &key.right);
If you are using this to decrypt a PIN block, you will need to XOR bytes 7 and 15 with 0xFF. (I am not 100% sure this should not be applied for the stream mode as well but my vendor is leaving it out.)
If it is a PIN block, it will be encrypted with 3-DES in ECB mode. If it is a data stream, it will be encrypted in CBC mode with a zero initialization vector.
(Did I mention I don’t much care for the spec?) It is interesting to note that the encryption side could be used in a non-hardware, tamper resistant security module if the server side (above) remembers and rejects keys that have been used previously. The technology is pretty neat. The ANSI spec leaves something to be desired but the technology is all right.
Good luck.
/Bob Bryan
For data encryption, the variant is 0000000000FF0000.0000000000FF0000 so you need to XOR bytes 5 and 13 instead of 7 and 15. In addition, you need an additional 3DES self-encryption step of each key parts (left and right).
Here is the relevant code in jPOS
https://github.com/jpos/jPOS/blob/master/jpos/src/main/java/org/jpos/security/jceadapter/JCESecurityModule.java#L1843-1856

Resources