Home › Forums › Ask the Flomies › Rewriting Customer Master Key ACR1255U-J1
Tagged: acr1255u-j1 customer master key
-
AuthorPosts
-
March 14, 2017 at 8:38 am #58984
Hi,
I want to rewrite the master key on my ACR1255U-J1.
First I have to get the random numbers from the device. Then I have to send an encrypted version of [those random numbers + new master key] to the device using AES 128 CBC encryption. But I can not find what I should use as initialization vector for the encryption. I have used 16 zeros as initialization vector but that bricked my reader (reader returned an OK response, but I can not authenticate with either the old key nor the new key).Can anyone help me rewrite the master key of the ACR1255U-J1?
March 14, 2017 at 11:03 am #58985March 14, 2017 at 11:05 am #58988I use Android,
ACR1255U-J1 SDK version downloaded from ACS website (1.0.0 Preview 8)March 14, 2017 at 11:16 am #58989Encryption/Decryption details: AES/CBC/NoPadding, IV = zeros (16 bytes).
I will see if a more Android literate dev can help you.
Regards,
ScottMarch 14, 2017 at 11:19 am #58990That’s exactly what I have used. It returned an OK response. But I can not authenticate with the new key. Also, the old key is not working anymore. I can’t get the reader to authenticate anymore.
March 14, 2017 at 11:28 am #58991Do you know what firmware your reader is using? If it is before 1.16.03, it is vulnerable to being bricked by sending escape commands too rapidly.
This is fixable but you would need to ship it off for repair.
Also, what are the lights on the device doing?Scott
March 14, 2017 at 11:35 am #58992I can still interact with the device, except authenticating and everything that requires authentication doesn’t work.
Calling
reader.getDeviceInfo(BluetoothReader.DEVICE_INFO_FIRMWARE_REVISION_STRING);
returns:
FWV 1.16.03��The lights function as normal (blinking until going to power saving mode).
- This reply was modified 7 years, 8 months ago by Mark.
March 14, 2017 at 11:51 am #58994Hello:
Try this code.
import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.math.BigInteger; import java.util.Arrays; /** * Created by dalvarez on 3/14/17. */ public class Encryption { /** * String keyhex * * @throws Exception */ static byte[] encrypt(String keyhex, String data) throws Exception { // fixed key; in real use key should be securely provided or generated // crude way of converting hex to bytes, better ways are possible byte[] key = new BigInteger (keyhex,16).toByteArray(); if( key.length > 16 ) key = Arrays.copyOfRange (key, 1, key.length); // maybe signed if( key.length != 16 ) throw new Exception ("key length wrong!"); // all-zero IV, only secure if key is unique every time byte[] IV = new byte[16]; // fixed plaintext for example, in real use obtain as needed byte[] plainbytes = data.getBytes(); // note: for ASCII-only data the Java default encoding is okay; // if real data can or could contain other chars, specify a // suitable encoding; "UTF-8" is good for most text-y data // ENCRYPT: we need to add zero padding ourself since JCE doesn't do that // Java makes this easy because arrays are initialized to all-zeros if( plainbytes.length %16 !=0 ) plainbytes = Arrays.copyOf (plainbytes, (plainbytes.length /16 +1)*16); Cipher aes = Cipher.getInstance ("AES/CBC/NoPadding"); aes.init (Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(IV)); byte[] cipherbytes = aes.doFinal (plainbytes); // crude way of converting bytes to hex, again better possible return cipherbytes; // alternatively just write to a file and let other tools handle } public static String decrypt(String keyhex, byte[] cipherbytes) throws Exception { // crude way of converting hex to bytes, better ways are possible byte[] key = new BigInteger (keyhex,16).toByteArray(); if( key.length > 16 ) key = Arrays.copyOfRange (key, 1, key.length); // maybe signed if( key.length != 16 ) throw new Exception ("key length wrong!"); // all-zero IV, only secure if key is unique every time byte[] IV = new byte[16]; // DECRYPT: assuming bytes read from file, or already converted from hex //same as above: Cipher aes = Cipher.getInstance ("AES/CBC/NoPadding"); Cipher aes = Cipher.getInstance ("AES/CBC/NoPadding"); aes.init (Cipher.DECRYPT_MODE, new SecretKeySpec (key, "AES"), new IvParameterSpec (IV)); byte[] resultbytes = aes.doFinal (cipherbytes); // now we need to remove the zero padding, which is ambiguous // this will damage data that actually has trailing zero bytes int i; for( i = resultbytes.length; --i>=0 && resultbytes[i]==0; ){} resultbytes = Arrays.copyOf (resultbytes, i+1); // for example just display, for real use adapt as desired // see above about encoding return new String (resultbytes); } public static void main(String[] arg) { try { byte[] cipherbytes = Encryption.encrypt("6c616d70736865657031323334353637", "Hello world"); System.out.println ("encrypt hex->" + new BigInteger(1, cipherbytes).toString(16)); String decript = Encryption.decrypt("6c616d70736865657031323334353637", cipherbytes); System.out.println ("decrypt chars->" + decript); } catch (Exception e) { e.printStackTrace(); } } }
March 15, 2017 at 4:09 am #58998That is exactly what I used (except I don’t use data.getBytes() but a method to convert hex string to actual bytes).
How can I reset the device so I can authenticate again?
March 15, 2017 at 4:18 am #58999I assume the reader checks whether the random numbers passed to the reader match the numbers that the reader sent originally?
March 15, 2017 at 9:04 pm #59003Hey Mark, there is no way for you to reset the device if the Master Key is unknown. You can send us your unit(s) and we can reflash it with stock firmware in order to get it operational again. That being said, I think it’s unlikely that the Master Key was successfully reset in your attempts. I say so because the process of resetting the Master Key is explicitly designed to avoid that scenario. It’s more likely that you’re entering the Master Key improperly during the authentication step.
RE: reader checks random number. Indeed, this is part of the process of authenticating with a host that has the current Master Key that matches what the reader has stored in it’s non-volatile memory. The random number is simple a unpredictable payload for which to sign with the key and confirm it matches the Host without exposing it to the data channel.
best,
RichardMarch 16, 2017 at 2:17 am #59006Hi Richard,
I spoke to a guy from ACS and he sent me a tool to reset the master key to the default master key. That worked perfectly.
I also found the solution to the problem: I had to use AES 128 ECB encryption instead of AES 128 CBC. When using ECB, rewriting the master key worked perfectly.
It sucks that the reader documentation is so inconsistent and even incorrect. ACS should update the documentation because The documentation says we should use CBC, which doesn’t work.
March 16, 2017 at 11:06 am #59009Mark, glad you got this sorted. The ACS folks told us not to share the tool so that’s why I only offered to fix it for you instead. Like many low cost manufacturers, ACS doesn’t invest in good documentation or in tools to help developers integrate NFC and related technologies. We’re passionate about these technologies and -as developers ourselves- are looking to ease the pain of integrating them while keeping hardware price points low. If you’d like to contribute with writing a step-by-step of what you’ve learned, I’ll drop it into our documentation for posterity.
best,
RichardDecember 21, 2018 at 5:16 am #64566Hi everyone. I’m now struggling with this issue. I’ve contacted ACS asking for the rewrite tool. But in the mean time I’d love to figure this out for myself.
I just can’t seem to get the encryption correct.
I’m using .Net AesCryptoServiceProvider.
PaddingMode : None
Cypher: EBC (Also tried CBC)
IV: 128bit (All zeros)As per for instructions in the reference manual I’m passing:
E0 00 00 60 00
This gets my random numbers (Or not so random if you reconnect the device each time)
I’m converting these into a byte array 16 long (128 bit)
I’m doing the same with my desired master keyI’m encrypting through AES as above and outputting the result back to hex
I then format the response…
E0 00 00 61 random encrypted [XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX] key [XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX]
It accepts the message but with a failed response.
Does anyone have a working code sample for this in .Net or Java?
- This reply was modified 5 years, 11 months ago by Stephen. Reason: typo
-
AuthorPosts
You must be logged in to reply to this topic.