Creating AES session key for Cipurse (Java Card)? - aes

I try to get into cipher, mutual authenticate and such and figured it might be good to see what is "on" the market. Now, cipurse states in its specifications a term like this to generate the session key:
k0 = AES (key = PAD2 (kP) XOR PAD (rT), kID) XOR kID
where k0 is the session key, kP is an on-card calculated key, rT is the response from the terminal. PAD stands for padding (leading zeroes), PAD 2 for double padding (leading zeros) and kID is the secret key from the card.
Now as far as I am aware I create a key this way:
AESKey k0_pre = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128, false);
k0_pre.clearKey();
k0_pre.setKey(key, (short) 0);
Now the one question I have is concerning just a little comma nameingly
key = PAD2 (kP) XOR PAD (rT), kID
setKey takes a byte[] and an offset, kID is not an offset cleary - should this comma be and "AND" or should those two expressions should be concatenated or something completely different?
The example kID in the guidelines is
53 45 43 5f 4d 45 4d 4f 52 59 20 4b 45 59 20 31
The result after for PAD2 (kP) XOR PAD (rT) is
00 00 00 00 b7 a0 d2 cb 01 15 25 3f c4 0d 43 8f
and the k0_pre is then to be:
72 4b e3 3e 05 47 b5 99 9c 78 13 9d 8b 25 94 e6
I just don't know how this AES Key is generated out of "2" input keys

I found the answer some place else:
The encryption of a 128-bit message block m using a 128-bit key k using the advanced encryption standard
AES is denoted by c := AES (key = k, m).
So, for my question the secret key kID is the message block, now it all makes sense!

Related

ASN.1 to DER encoding

I'm trying to generate RSA public key I have ASN.1 code I need to encode with DER
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, 7120255303029382831
publicExponent INTEGER 4242026487
}
My DER code 30 10 08 02 62 D0 3A 79 2F 28 5E AF 02 04 FC D8 2F F7
My DER code is wrong please help me how can I write as correctly
You can/should use a tool to do that.
https://asn1.io/asn1playground/
Compile your spec
Encode a value
Read the result

How does the Hex data of a .wav file reads?

I was trying to read a .wav file with java and apparently the problem is that I don't understand how the Hex figures are supposed to be read.
Here are the first lines of DATA from a .wav (32 Bits per sample, 2 Channels) on a Hex editor :
64 61 74 61 00 1A 01 00 data.....
1D F6 FB 3D 84 DF FB 3D öû=„ßû=
4B 03 03 3E 4B 03 03 3E K..>K..>
D5 F8 08 3E D5 F8 08 3E Õø.>Õø.>
C6 48 0F 3E C6 48 0F 3E ÆH.>ÆH.>
So here is what I thought : the first value from the first channel should be read : 3D FB F6 1D, which would mean 1039922717
And so I take that number and substract 2^31 and I get -1107560931 and that would be the first value. But then I compare this to the value I get from MATLAB audioread and I get 264200656 as first value. Why ?

Mifare Desfire Wrapped Mode: How to calculate CMAC?

When using Desfire native wrapped APDUs to communicate with the card, which parts of the command and response must be used to calculate CMAC?
After successful authentication, I have the following session key:
Session Key: 7CCEBF73356F21C9191E87472F9D0EA2
Then when I send a GetKeyVersion command, card returns the following CMAC which I'm trying to verify:
<< 90 64 00 00 01 00 00
>> 00 3376289145DA8C27 9100
I have implemented CMAC algorithm according to "NIST special publication 800-38B" and made sure it is correct. But I don't know which parts of command and response APDUs must be used to calculate CMAC.
I am using TDES, so MAC is 8 bytes.
I have been looking at the exact same issue for the last few days and I think I can at least give you some pointers. Getting everything 'just so' has taken some time and the documentation from NXP (assuming you have access) is a little difficult to interpret in some cases.
So, as you probably know, you need to calculate the CMAC (and update your init vec) on transmit as well as receive. You need to save the CMAC each time you calculate it as the init vec for the next crypto operation (whether CMAC or encryption etc).
When calculating the CMAC for your example the data to feed into your CMAC algorithm is the INS byte (0x64) and the command data (0x00). Of course this will be padded etc as specified by CMAC. Note, however, that you do not calculate the CMAC across the entire APDU wrapping (i.e. 90 64 00 00 01 00 00) just the INS byte and data payload is used.
On receive you need to take the data (0x00) and the second status byte (also 0x00) and calculate the CMAC over that. It's not important in this example but order is important here. You use the response body (excluding the CMAC) then SW2.
Note that only half of the CMAC is actually sent - CMAC should yield 16 bytes and the card is sending the first 8 bytes.
There were a few other things that held me up including:
I was calculating the session key incorrectly - it is worth double checking this if things are not coming out as you'd expect
I interpreted the documentation to say that the entire APDU structure is used to calculate the CMAC (hard to read them any other way tbh)
I am still working on calculating the response from a Write Data command correctly. The command succeeds but I can't validate the CMAC. I do know that Write Data is not padded with CMAC padding but just zeros - not yet sure what else I've missed.
Finally, here is a real example from communicating with a card from my logs:
Authentication is complete (AES) and the session key is determined to be F92E48F9A6C34722A90EA29CFA0C3D12; init vec is zeros
I'm going to send the Get Key Version command (as in your example) so I calculate CMAC over 6400 and get 1200551CA7E2F49514A1324B7E3428F1 (which is now my init vec for the next calculation)
Send 90640000010000 to the card and receive 00C929939C467434A8 (status is 9100).
Calculate CMAC over 00 00 and get C929939C467434A8A29AB2C40B977B83 (and update init vec for next calculation)
The first half of our CMAC from step #4 matches the 8 byte received from the card in step #3
Sry for my English,- its terrible :) but it's not my native language. I'm Russian.
Check first MSB (7 - bit) of array[0] and then shiffting this to the left. And then XOR if MSB 7 bit was == 1;
Or save first MSB bit of array[0] and after shiffting put this bit at the end of array[15] at the end (LSB bit).
Just proof it's here:
https://www.nxp.com/docs/en/application-note/AN10922.pdf
Try this way:
Zeros <- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SessionKey <- 00 01 02 03 E3 27 64 0C 0C 0D 0E 0F 5C 5D B9 D5
Data <- 6F 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00
First u have to encrypt 16 bytes (zeros) with SesionKey;
enc_aes_128_ecb(Zeros);
And u get EncryptedData.
EncryptedData <- 3D 08 A2 49 D9 71 58 EA 75 73 18 F2 FA 6A 27 AC
Check bit 7 [MSB - LSB] of EncryptedData[0] == 1? switch i to true;
bool i = false;
if (EncryptedData[0] & 0x80){
i = true;
}
Then do Shiffting of all EncryptedData to 1 bit <<.
ShiftLeft(EncryptedData,16);
And now, when i == true - XOR the last byte [15] with 0x87
if (i){
ShiftedEncryptedData[15] ^= 0x87;
}
7A 11 44 93 B2 E2 B1 D4 EA E6 31 E5 F4 D4 4F 58
Save it as KEY_1.
Try bit 7 [MSB - LSB] of ShiftedEncryptedData[0] == 1?
i = false;
if (ShiftedEncryptedData[0] & 0x80){
i = true;
}
Then do Shiffting of all ShiftedEncryptedData to 1 bit <<.
ShiftLeft(ShiftedEncryptedData,16);
And now, when i == true - XOR the last byte [15] with 0x87
if (i){
ShiftedEncryptedData[15] ^= 0x87;
}
F4 22 89 27 65 C5 63 A9 D5 CC 63 CB E9 A8 9E B0
Save it as KEY_2.
Now we take our Data (6F 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00)
As Michael say's - pad command with 0x80 0x00...
XOR Data with KEY_2 - if command was padded, or KEY_1 if don't.
If we have more like 16 bytes (32 for example) u have to XOR just last 16 bytes.
Then encrypt it:
enc_aes_128_ecb(Data);
Now u have a CMAC.
CD C0 52 62 6D F6 60 CA 9B C1 09 FF EF 64 1A E3
Zeros <- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SessionKey <- 00 01 02 03 E3 27 64 0C 0C 0D 0E 0F 5C 5D B9 D5
Key_1 <- 7A 11 44 93 B2 E2 B1 D4 EA E6 31 E5 F4 D4 4F 58
Key_2 <- F4 22 89 27 65 C5 63 A9 D5 CC 63 CB E9 A8 9E B0
Data <- 6F 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CMAC <- CD C0 52 62 6D F6 60 CA 9B C1 09 FF EF 64 1A E3
C/C++ function:
void ShiftLeft(byte *data, byte dataLen){
for (int n = 0; n < dataLen - 1; n++) {
data[n] = ((data[n] << 1) | ((data[n+1] >> 7)&0x01));
}
data[dataLen - 1] <<= 1;
}
Have a nice day :)

WM-Bus extended layer decoding

I am trying to decrypt wm-bus telegram from Kamstrup Multical21 in C1 mode with Extended Link Layer.
The payload together with ELL info is following:
23 44 2D 2C 45 45 71 63 1B 16 8D 20 6A 31 FB 7C 20 39 A3 79 60 4B 90 BD FC BE 8D D8 CB 18 CE 77 DC 41 CE 8C
Analysing CI = 8D I found that there is a ELL with following data:
CI (1 byte) CC(1 byte) ACC(1 byte) SN(4 bytes) CRC(2 bytes)
8D 20 6A 31 FB 7C 20 39 A3
The documentation says that the buffer which should be decrypted shall contain CRC from ELL, i.e:
39 A3 79 60 4B 90 BD FC BE 8D D8 CB 18 CE 77 DC 41 CE 8C
I have got the AES key from the Manufacturer:
B9 7A 6D 4E C2 74 A4 6D 87 0E 31 27 D9 A0 AF 63
Initialization vector for ELL shall be:
M-field A-field CC-field SN-field FN BC
2D 2C 45 45 71 63 1B 16 20 31 FB 7C 20 00 00 00
After decrypting, I get the following result:
08 3a 5f ce b2 8d 51 97 94 a2 5b fb 61 ab 2e c0
e4 20 c8 2a 43 ff 3a 75 6f 93 d0 ac 8c 79 b7 a1
Since there is no 2F 2F in the beginning, something is wrong!
Can somebody help me and tell what I have done wrong?
Thanks in advance.
I had a look in the latest Kamstrup docs ("Wireless M-Bus Communication Kamstrup Water Meters - MULTICAL® 21 and flowIQ® water meters Mode C1 according to EN 13757-4:2013")
When I decrypt your packet I find:
25877968217E8E01000000000000000000
Firstly, it seems the Kamstrup decrypted packets does not start with 2F 2F.
The first 2 bytes of the decrypted packet is supposedly the PLCRC (I can't confirm that right now - don't have immediate access to the standard that defines the crc polynomial algorithm), and then the next byte is 79, which means it is a Compact Frame, then the next 4 bytes are 2 more CRCs, and then the next 2 bytes 0100 is probably the Info, which is manufacturer specific and I don't know how to interpret that yet.
This meter is probably R type 1, right? (on the face place, the "Con.:" parameter's 3rd last digit should be a 1) So its format would be [Info][Volume][Target Volume] - 2 bytes, 4 bytes, 4 bytes - I kind of assume that, since this packet is a compact packet, so I don't get the actual format the long packet would have, e.g. number of decimals - which normally you'd need - but your values are zeroes? so decimals doesn't matter. (the 'long' packet of course is every 6th packet or so?)
The IV I get is:
2D2C454571631B162031FB7C20000000
which is exactly the same as yours.
The encrypted packet I use is:
39A379604B90BDFCBE8DD8CB18CE77DC41
so I exclude the CE and 8C you had on yours?
When I put them in, the decrypted packet becomes:
25877968217E8E01000000000000000000BB49
which is pretty much the same packet with some more crc stuff at the back, I suspect, so I really do not get what you do to decrypt, since your result is completely different?
Ok, maybe you use AES/CBC/NoPadding, as in OpenMUC.
Kamstrup uses AES/CTR/NoPadding. That is how they don't have to decrypt multiples of 16 byte blocks? The way that looks in my Java code is as follows:
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
the hints here are very helpfull. There's one obstacle I stumbled across with the given message. The Length-Field is wrong and there are 2 bytes of garbage at the end.
I guess the original message was encoded in frame format B. That means the length field includes the frame CRCs and should be corrected after the CRCs are removed. After correcting the length to 0x21 (33 bytes + L-Field), I get the correct message and also can verify that the first 2 bytes of the decoded message contain the CRC16 of the remaining message.

Matlab reading endian-incorrect binary data input / interpreting as uint32

While writing this post, I attempted b = fread(s, 1, 'uint32')
This would work great, but my poor data is sent LSB first! (no I can not change this)
Before, I was using b = fread(s, 4)' which gives me a vector similar to [47 54 234 0].
Here is my input stream:
0A
0D 39 EA 00 04 39 EA 00
4B 39 EA 00 D0 38 EA 00
0A
etc...
I can successfully delimit by 0x0A by
while ~isequal(fread(s, 1), 10) end
Basically I need to get the array of uint32s represented by [00EA390D 00EA3904 00EA394B 00EA38D0]
The documentation for swapbytes doesn't help me much and the uint32 operator operates on individual elements!!
The matlab fread function directly supports little endian machine format. Just set the 5th argument of the fread function to the string "L".
b = fread(s, 4, 'uint32',0,'l');