Display image on Pebble via AppMessage - java

I am trying to display a 128px * 128px image on Pebble, sent from Android over AppMessage.
In Android app, I have a BitmapFactory ARGB_8888 bmp, and I do:
byte pbi[] = new byte[16*128];
for(int i = 0; i < 128; i++) {
for(int j = 0; j < 128; j++) {
if(bmp.getPixel(i, j) >= 0x7FFFFFFF) {
pbi[i*16] |= 1 << (j % 8); //set pixel (white)
}
pbi[i*16] &= ~(1 << (j % 8)); //explicitly set = 0 (black)
}
}
PebbleDictionary data;
byte send[];
for (int k = 0; k < 128; k++){
data = new PebbleDictionary();
send = new byte[16];
send = Arrays.copyOfRange(pbi, k*16, (k+1)*16-1);
data.addBytes(KEY_IMG, send);
data.addInt16(KEY_ROW, (byte)k);
PebbleKit.sendDataToPebble(getApplicationContext(), PEBBLE_APP_UUID, data);
}
Pebble has:
static int transNum;
static uint8_t received[128][16] = {0};
static void in_received_handler(DictionaryIterator *iter, void *context) {
Tuple *img_tuple = dict_find(iter, KEY_IMG);
Tuple *row_tuple = dict_find(iter, KEY_ROW);
if (img_tuple && row_tuple) {
memcpy(img_data[(int)(row_tuple->value->cstring)], img_tuple->value->data, 16);
}
}
Which should be displayed by:
static void window_load(Window *window) {
static Window *window;
static BitmapLayer *img_layer;
static GBitmap img;
static void window_load(Window *window) {
L img_layer = bitmap_layer_create( (GRect) {
.origin = {8, 20},
.size = {128, 128}
});
img = (GBitmap) {
.addr = img_data,
.bounds = GRect(8, 20, 128, 128),
.row_size_bytes = 16,
};
bitmap_layer_set_bitmap(img_layer, &img);
bitmap_layer_set_alignment(img_layer, GAlignCenter);
layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(img_layer));
display_no_img();
}
But on window_load, I get the expected black square, but I can't figure how to make it load the received data.
Edit:
It's hard for me to keep the code above updated, but it's pretty representative. I'm hoping someone can tell me what to do to make it load the received bytes. I thought the secret was in .addr = img_data, alas.. Thanks.

You should take a look at the Pebble-faces example. It uses JavaScript but you could probably completely reuse the C part and just change the phone code.

Related

Bitwise representation into a byte array function

I'm trying to do a memory writing program with bits as part of a CPU simulating program and I don't understand something. I'm making a function to write int value into the memory which is byte double array broken down into segments. Now, I don't understand why the following writeWord function is not working probably, I'll post relevant code as well as the function.
public class RealMemory implements Memory {
public static final int BYTES_PER_INT = 4;
public static final int BITS_PER_BYTE = 8;
private final int segmentSize;
private final int numberOfSegments;
private byte[][] memory;
public RealMemory (int segmentSize, int numberOfSegments) {
this.segmentSize = segmentSize;
this.numberOfSegments = numberOfSegments;
this.memory = new byte[this.numberOfSegments][this.segmentSize];
}
private byte[] getSegment(int segment) {
assert(segment >= 0 && segment < numberOfSegments);
return memory[segment];
}
public void writeWord (int segment, int offset, int value) {
assert (offset >= 0 && offset < segmentSize - BYTES_PER_INT
&& offset % BYTES_PER_INT == 0);
byte[] byteword = new byte[BYTES_PER_INT];
int mask = 1;
for (int i=offset; i < offset + BYTES_PER_INT; i++) {
byteword[i-offset] = (byte) (value & mask);
mask <<= 1;
getSegment(segment)[i]=byteword[i-offset];
}
}
}
I know the way I try to breakdown the value into bits is wrong, I just don't understand bitwise operation needed here fully is my guess. Any help?
Your problem is mask = 1. You don't read bytes, but single bits instead.
To read bytes, use int mask = (1 << BITS_PER_BYTE) - 1; and mask <<= BITS_PER_BYTE;. Once you masked out the relevant parts you also have to shift it to the right. As Stanislav Bashkyrtsev suggested, this can be done directly on the value instead of shifting the mask.
int mask = (1 << BITS_PER_BYTE) - 1;
for (int i=offset; i < offset + BYTES_PER_INT; i++) {
byteword[i-offset] = (byte) (value & mask);
value >>= BITS_PER_BYTE;
getSegment(segment)[i]=byteword[i-offset];
}

Is there any pointer feature in java to pass the byte array?

I need to divide a byte array into 3 parts and process them one by one
The first 120 data array is filled in callback function of a Bluetooth device read request, so it's impossible for me to change
byte[] data = new byte[120];
------
byte[] buf = new byte[40];
for (int i = 0; i < 3; ++i) {
System.arraycopy(data, i * 40, packetBuffer, 0, 40);
processDataStream(buf);
}
If in c/c++, I can use pointer so no need to call copy.
In Java, is arraycopy the best way? is there any more efficient way?
Thanks in advance
In most cases you'd just specify an offset and provide it to your method:
byte[] buf = new byte[40];
for (int i = 0; i < 3; ++i) {
processDataStream(buf, i * 40);
}
Then you only need to apply it:
processDataStream(byte[] buf, int offset) {
for (int i = offset; i < offset + 40; i++) {
...
}
}

Processing Sketch "Array Out of Bounds Exception" (when converting string to int array)

I am a student working on my first robotics project. I need help fixing a program that was provided by the manufacturer when I purchased an IR camera (similar to the Wii IR camera). The manufacturer provided two sketches. The first is an Arduino sketch that takes the i2c input and prints it out via the serial monitor. I don't have a problem with this sketch, but am providing it for reference.
#include <Wire.h>
int IRsensorAddress = 0xB0;
//int IRsensorAddress = 0x58;
int slaveAddress;
int ledPin = 13;
boolean ledState = false;
byte data_buf[16];
int i;
int Ix[4];
int Iy[4];
int s;
void Write_2bytes(byte d1, byte d2)
{
Wire.beginTransmission(slaveAddress);
Wire.write(d1); Wire.write(d2);
Wire.endTransmission();
}
void setup()
{
slaveAddress = IRsensorAddress >> 1; // This results in 0x21 as the address to pass to TWI
Serial.begin(19200);
pinMode(ledPin, OUTPUT); // Set the LED pin as output
Wire.begin();
// IR sensor initialize
Write_2bytes(0x30, 0x01); delay(10);
Write_2bytes(0x30, 0x08); delay(10);
Write_2bytes(0x06, 0x90); delay(10);
Write_2bytes(0x08, 0xC0); delay(10);
Write_2bytes(0x1A, 0x40); delay(10);
Write_2bytes(0x33, 0x33); delay(10);
delay(100);
}
void loop()
{
ledState = !ledState;
if (ledState) { digitalWrite(ledPin, HIGH); }
else { digitalWrite(ledPin, LOW); }
//IR sensor read
Wire.beginTransmission(slaveAddress);
Wire.write(0x36);
Wire.endTransmission();
Wire.requestFrom(slaveAddress, 16); // Request the 2 byte heading (MSB comes first)
for (i = 0; i < 16; i++) { data_buf[i] = 0; }
i = 0;
while (Wire.available() && i < 16) {
data_buf[i] = Wire.read();
i++;
}
Ix[0] = data_buf[1];
Iy[0] = data_buf[2];
s = data_buf[3];
Ix[0] += (s & 0x30) << 4;
Iy[0] += (s & 0xC0) << 2;
Ix[1] = data_buf[4];
Iy[1] = data_buf[5];
s = data_buf[6];
Ix[1] += (s & 0x30) << 4;
Iy[1] += (s & 0xC0) << 2;
Ix[2] = data_buf[7];
Iy[2] = data_buf[8];
s = data_buf[9];
Ix[2] += (s & 0x30) << 4;
Iy[2] += (s & 0xC0) << 2;
Ix[3] = data_buf[10];
Iy[3] = data_buf[11];
s = data_buf[12];
Ix[3] += (s & 0x30) << 4;
Iy[3] += (s & 0xC0) << 2;
for (i = 0; i < 4; i++)
{
if (Ix[i] < 1000)
Serial.print("");
if (Ix[i] < 100)
Serial.print("");
if (Ix[i] < 10)
Serial.print("");
Serial.print(int(Ix[i]));
Serial.print(",");
if (Iy[i] < 1000)
Serial.print("");
if (Iy[i] < 100)
Serial.print("");
if (Iy[i] < 10)
Serial.print("");
Serial.print(int(Iy[i]));
if (i < 3)
Serial.print(",");
}
Serial.println("");
delay(15);
}
The second sketch is a Processing sketch that draws a visual representation of the IR signal being seen by the camera. This is where I am having the issue. Sometimes when I start the program, it runs correctly. I get a printout of 8 numbers (four (x,y) coordinates) and the blobs representing the IR signals can be seen via the Processing window. But more often than not, I get an "ArrayIndexOutofBoundsException" followed by the number of the index being called for the output array.
Based on my searching and requesting help on the Processing forum, it seems that there may be an issue with converting the string from the serial output of the Arduino sketch to an integer array in the Processing sketch. The only response I got from the Processing forum was a link suggesting that I add tabs ("\t") to separate the string elements before I try to split them and convert them. But that didn't really do anything in terms of fixing the Array error. I originally added a line to print the length of the array so I could see that it was correct (it should be 8), and the length of the array kept changing. I'm pretty sure the error is occurring at line 29 to 40.
This is the Processing sketch:
// Example by Tom Igoe
// Modified for http://www.DFRobot.com by Lumi, Jan. 2014
/*
This code should show one colored blob for each detected IR source (max four) at the relative
position to the camera.
*/
import processing.serial.*;
int lf = 10; // Linefeed in ASCII
String myString = null;
Serial myPort; // The serial port
void setup() {
// List all the available serial ports
println(Serial.list());
// Open the port you are using at the rate you want:
myPort = new Serial(this, Serial.list()[1], 19200);
myPort.clear();
// Throw out the first reading, in case we started reading
// in the middle of a string from the sender.
myString = myPort.readStringUntil(lf);
myString = null;
size(800, 800);
//frameRate(30);
}
void draw() {
background(77);
//while (myPort.available() > 0) {
myString = myPort.readStringUntil(lf);
if (myString != null) {
int[] output = int(split(myString, ','));
println(myString); // display the incoming string
int xx = output[0];
int yy = output[1];
int ww = output[2];
int zz = output[3];
int xxx = output[4];
int yyy = output[5];
int www = output[6];
int zzz = output[7];
ellipseMode(RADIUS); // Set ellipseMode to RADIUS
fill(255, 0, 0); // Set fill to white
ellipse(xx, yy, 20, 20);
ellipseMode(RADIUS); // Set ellipseMode to RADIUS
fill(0, 255, 0); // Set fill to white
ellipse(ww, zz, 20, 20);
ellipseMode(RADIUS); // Set ellipseMode to RADIUS
fill(0, 0, 255); // Set fill to white
ellipse(xxx, yyy, 20, 20);
ellipseMode(RADIUS); // Set ellipseMode to RADIUS
fill(255); // Set fill to white
ellipse(www, zzz, 20, 20);
}
}
Any help would be appreciated. I have been banging my head against this thing for over a week now, but I don't want to give up.

Parse an integer with 9 digits into an array of colors

I have an array of nine digit numbers with a range of 0 - 999,999,999. I want to be able to parse them into an array of Colors. I then want to be able to convert the array of colors back to the array of numbers.
This is what I want to be able to do:
Color[] colors = encode(intEnter);//intEnter is any integer which is 8 or 9 characters long.
int decode = decode(colors);//returns intEnter
I would like to do new Color(999, 999, 999), but it only supports up to 255.
How can I create an array of Colors to encode larger numbers than rgb supports and then decode it back?
Rather than combining 3 bytes to form a 9 digit integer, create a color using the 3 bytes. You have to unsign them first, though, to offset the range to 0 to 255 rather than -128 to 127.
Consider you have a byte[] of size 100_000 full of bytes:
byte[] bytes = new byte[100_000];
new Random().nextBytes(bytes); //fills array with bytes; simulates bytes from stream
An unsigned byte value cannot fit in a byte, so we must use a short[] or int[]. To convert a signed byte to an unsigned byte, we use the bitewise & against 255 (more commonly seen as 0xff):
int[] unsign(byte[] bytes) {
int[] unsignedBytes = new int[bytes.length];
for(int i = 0; i < unsignedBytes.length; i++) {
unsignedBytes[i] = bytes[i] & 0xff;
}
return unsignedBytes;
}
To group these into 3s, we need to first ensure the amount of bytes we have is divisble by 3. For example, if we have an array of [101, 74, 88, 21], we could either remove the 21 to create a color, or add 2 0s to create 2 colors. The first choice results in lost data, so we will go with the second option:
int[] sizeArray(int[] unsignedBytes) {
int length = unsignedBytes.length;
int bytesPerColor = 3;
int remainder = length % bytesPerColor;
int bytesNeeded = bytesPerColor - remainder;
int numOfBytes = remainder > 0 ? length + bytesNeeded : length;
int[] sizedArray = new int[numOfBytes];
System.arrayCopy(unsignedBytes, 0, sizedArray, length);
return sizedArray;
}
Now for the encoding. For every 3 bytes, we generate a color:
Color[] encode(int[] unsignedBytes) {
Color[] colors = new Color[unsignedBytes.length / 3];
for(int i = 0, position = 0; i < colors.length; i++) {
int r = unsignedBytes[position++];
int g = unsignedBytes[position++];
int b = unsignedBytes[position++];
colors[i] = new Color(r, g, b);
}
return colors;
}
To decode, simply grab the RGB values from each color:
int[] decode(Color[] colors) {
int[] unsignedBytes = new int[colors.length * 3];
int position = 0;
for(Color color : colors) {
unsignedBytes[position++] = color.getRed();
unsignedBytes[position++] = color.getGreen();
unsignedBytes[position++] = color.getBlue();
}
return unsignedBytes;
}
To sign the bytes, simply cast them back to bytes:
byte[] sign(int[] unsignedBytes) {
byte[] signedBytes = new byte[unsignedBytes.length];
for(int i = 0; i < signedBytes.length; i++) {
signedBytes[i] = (byte) unsignedBytes[i];
}
return signedBytes;
}
You could have an Encoder and a Decoder class, which takes care of the signing and unsigning for you if needed:
class Encoder {
public Color[] encode(byte[] signedBytes) {
return encode(unsign(signedBytes));
}
public Color[] encode(int[] unsignedBytes) {
//...
}
private int[] unsign(byte[] signesBytes) {
//...
}
}
class Decoder {
public byte[] decode(Color[] colors) {
//receive unsigned bytes from colors
return sign(unsignedBytes);
}
private byte[] sign(int[] unsignedBytes) {
//...
}
}
Wrote this from my phone, so let me know if there are any problems
I have found a way to answer my own question, but it is a bit sloppy. Basically I can subtract 16777215 from the number and create a color with its rgb set as 16777215. It will do this until one number is left over and it will create a color with the remaining number. For each number in the array it create a color array with the first color being the the value of how many colors in the array make up the specific number.
Here is my code:
Color[] colors = encode(999999999);
Color[] colors2 = encode(120658366);
Color[] colors3 = encode(596820492);
Color[] colors4 = encode(123098765);
Color[] colorsFinal = new Color[colors.length + colors2.length + colors3.length + colors4.length];
int nextIndex=0;
for(Color c : colors){
colorsFinal[nextIndex] = c;
nextIndex++;
}
for(Color c : colors2){
colorsFinal[nextIndex] = c;
nextIndex++;
}
for(Color c : colors3){
colorsFinal[nextIndex] = c;
nextIndex++;
}
for(Color c : colors4){
colorsFinal[nextIndex] = c;
nextIndex++;
}
int nextKey = 0;
for(int i = 0; i < colorsFinal.length; i++){
if(i == nextKey){
int count = 1 + (colorsFinal[i].getRGB() + 16777216);
System.out.println(decode(Arrays.copyOfRange(colorsFinal, i, i + count)));
nextKey+=count;
i = nextKey-1;
}
}
Encode:
public static Color[] encode(int number){
int count = number / 16777215;
if(number % 16777215 > 0){
count++;
}
Color[] colors = new Color[count+1];
for(int i = 0; i < colors.length; i++){
if(i == 0){
colors[i] = new Color(count);
}else{
if(number > 16777215){
number = number - 16777215;
colors[i] = new Color(16777215);
}else{
colors[i] = new Color(number);
}
}
}
return colors;
}
Decode:
public static int decode(Color[] colors){
if(colors.length > 1){
int total = 0;
for(int i = 1; i < colors.length; i++){
total += (colors[i].getRGB() + 16777216);
}
return total;
}else{
return 0;
}
}
This is the output:
999999999
120658366
596820492
123098765
This works to encode a 9 digit number into an array of colors, but I am sure it can be improved. In fact this works for any integer which is positive.

DES Send and Receive Modes for DESFire Authentication

I'm trying to authenticate DESFire card with my android application. I use the example in this link to decypher the bytes I got from the card. For that, I ruled out padding in decryption (commented out below), because DESFire documentation points it out. Also, if I don't do so, decryption returns 7 bytes for input of 8 bytes. Below are DES and TripleDES decryption functions I use:
public static byte[] TripleDES_Decrypt(byte[] data,byte[][] keys)
{
int i;
byte[] tmp = new byte[data.length];
byte[] bloc = new byte[8];
K = generateSubKeys(keys[0]);
K1 = generateSubKeys(keys[1]);
K2 = generateSubKeys(keys[2]);
for (i = 0; i < data.length; i++) {
if (i > 0 && i % 8 == 0) {
bloc = encrypt64Bloc(bloc,K2, true);
bloc = encrypt64Bloc(bloc,K1, false);
bloc = encrypt64Bloc(bloc,K, true);
System.arraycopy(bloc, 0, tmp, i - 8, bloc.length);
}
if (i < data.length)
bloc[i % 8] = data[i];
}
bloc = encrypt64Bloc(bloc,K2, true);
bloc = encrypt64Bloc(bloc,K1, false);
bloc = encrypt64Bloc(bloc,K, true);
System.arraycopy(bloc, 0, tmp, i - 8, bloc.length);
//tmp = deletePadding(tmp);
return tmp;
}
public static byte[] decrypt(byte[] data, byte[] key) {
int i;
byte[] tmp = new byte[data.length];
byte[] bloc = new byte[8];
K = generateSubKeys(key);
for (i = 0; i < data.length; i++) {
if (i > 0 && i % 8 == 0) {
bloc = encrypt64Bloc(bloc,K, true);
System.arraycopy(bloc, 0, tmp, i - 8, bloc.length);
}
if (i < data.length)
bloc[i % 8] = data[i];
}
bloc = encrypt64Bloc(bloc,K, true);
System.arraycopy(bloc, 0, tmp, i - 8, bloc.length);
//tmp = deletePadding(tmp);
return tmp;
}
According to DesFire document, I need two modes of decryption, send and receive. This blog post has some explanation about it.
However, the DESFire crypto is a bit different from the normal DES/CBC scheme: The PCD uses DES “send mode” when sending data (xor before DES), and the card uses DES “recieve mode” when recieving data (xor after DES). But when the PCD recieves data, it uses normal DES/CBC mode (xor after DES), and the card uses normal DES send mode when sending data (xor before DES).
And in Android side I follow the examples and recommendations:
// connected to tag and application
// result = encoded(randB) + af
byte[] result = idTag.transceive(Utils.wrapMessage((byte)0x0a, new byte[]{(byte)0x0}));
byte[] b0 = new byte[8];
for(int i = 0; i < 8; i++) {
b0[i] = result[i];
}
// key
byte[] key = new byte[] {(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0 };
byte[][] keys = new byte[3][];
keys[0]=key; keys[1]=key; keys[2]=key;
// decrypt encoded(randB)
byte[] r0 = DES.TripleDES_Decrypt(b0, keys);
// generate randA (integer 0-7 for trying)
byte[] nr = new byte[8];
for(int i = 0; i < 8; i++) {
nr[i] = Byte.parseByte(Integer.toString(i), 16);
}
// decrypt randA
byte[] b1 = DES.TripleDES_Decrypt(nr, keys);
// shift randB and get randB'
byte[] r1 =new byte[8];
for(int i = 0; i < 7; i++) {
r1[i] = r0[i + 1];
}
r1[7]=r0[0];
// concat (randA + randB')
byte[] b2 = new byte[16];
for(int i = 0; i < 16; i++)
{
if(i <= 7) {
b2[i] = b1[i];
} else {
b2[i] = r1[i - 8];
}
}
// XOR (randA + randB') with IV
// IV is told to be consisting of 0's,
// but XOR something with 0 results the same?
for(int i=0;i<16;i++) {
b2[i] = (byte) (b2[i] ^ (byte)0x0);
}
// send AF and decrypt(A+B)
// wrap message adds needed wrapping to message (90 to left, offset bytes etc.)
result = isodepTag.transceive(Utils.wrapMessage((byte)0xaf, DES.TripleDES_Decrypt(b2, keys)));
I get the first result, the encrypted randB. However, the second "result" is always "91ae", means authentication error. I'm doing something wrong here, send wrong data to card.
Can anyone tell me what must I change in the code to work in these modes? What should I XOR with data before/after TripleDES?
Not the real question, but I read that default "Key" in DesFire card is 16 zero bytes. Also the document points that I need to use TripleDES for 16 bytes of key, DES for 8 bytes of key. So I'm using and need to use TripleDES as I haven't changed the default key, am I right?
For those who need the know about CipherBlockChaining.
EDIT: I found out that I need to do XORing before and after TripleDES and I mustn't touch TripleDES's internal operations at all. I will be trying that in a while.
Deleted the inner TripleDES lines, just saying for the ones seeing the question for the first time.
OK I got the solution. My mistake was that I was sending
3DES(randA + randB')
But I should send
3DES(randA) + 3DES(randB' XOR 3DES(randA))
Here's the authentication code for Android/Java (it's so sad that this is the only one that can be found on the net currently!):
The actual authentication code:
// send initial authentication request
byte[] result = idTag.transceive(Utils.wrapMessage((byte)0x0a, new byte[]{(byte)0x0}));
// get encrypted(randB) from the response
byte[] b0 = new byte[8];
for(int i = 0; i < 8; i++) {
b0[i] = result[i];
}
// 16 bytes default key
byte[] key = new byte[] {(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,
(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0 };
// keys for TripleDes
byte[][] keys = new byte[3][];
keys[0] = key; keys[1] = key; keys[2] = key;
// decrypt encoded(randB)
byte[] r0 = DES.TripleDES_Decrypt(b0, keys);
// generate randA (integer 0-7 for trying, should randomize for real-life use)
byte[] nr = new byte[8];
for(int i = 0; i < 8; i++) {
nr[i] = Byte.parseByte(Integer.toString(i), 16);
}
// decrypt randA, should XOR with IV, but IV is all 0's, not necessary
byte[] b1 = DES.TripleDES_Decrypt(nr, keys);
// shift randB one byte left and get randB'
byte[] r1 =new byte[8];
for(int i = 0; i < 7; i++) {
r1[i] = r0[i + 1];
}
r1[7]=r0[0];
// xor randB' with randA and decrypt
byte[] b2 = new byte[8];
for(int i = 0; i < 8; i++) {
b2[i] = (byte) (b1[i] ^ r1[i]);
}
b2 = DES.TripleDES_Decrypt(b2, keys);
// concat (randA + randB')
byte[] b1b2 = new byte[16];
for (int i = 0; i < b1b2.length; i++) {
if(i <= 7) {
b1b2[i] = b1[i];
} else {
b1b2[i]=b2[i-8];
}
}
result = idTag.transceive(Utils.wrapMessage((byte)0xaf, b1b2));
TripleDes is the one in the question. wrapMessage function:
public static byte[] wrapMessage (byte command, byte[] parameters) throws Exception {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
stream.write((byte) 0x90);
stream.write(command);
stream.write((byte) 0x00);
stream.write((byte) 0x00);
if (parameters != null) {
stream.write((byte) parameters.length);
stream.write(parameters);
}
stream.write((byte) 0x00);
return stream.toByteArray();
}
EDIT: Thanks to VGe0rge, we found out the reason why this authentication doesn't work from time to time. Instead of calling the 3DES function in the question, just call:
Cipher.getInstance("DESede/CBC/NoPadding");
Ismat, did you try to write data to the DESFIRE files?
As you explained, when sending data to the card: The PCD uses DES “send mode” when sending data (xor before DES), and the card uses DES “recieve mode” when recieving data (xor after DES)
So I can't get the proper code in order to implement the TDES with the XOR before..I need to do all the crypt-decrypt-crypt and the process is to slow for my application:
res = criptoTransformDec.TransformBlock(datosEscribir, 0, 8, datosEscribir, 0);
res = criptoTransformEnc.TransformBlock(datosEscribir, 0, 8, datosEscribir, 0);
res = criptoTransformDec1.TransformBlock(datosEscribir, 0, 8, datosEscribir, 0);
int l_iAux = 0;
while (l_iAux < (datosEscribir.Length - 8))
{
criptoTransformDec2 = desDec.CreateDecryptor(claveSes1, tdesInitialVector);
//desEnc2 = new DESCryptoServiceProvider();
criptoTransformEnc2 = desEnc.CreateEncryptor(claveSes2, tdesInitialVector);
//desDec3 = new DESCryptoServiceProvider();
criptoTransformDec3 = desDec.CreateDecryptor(claveSes1, tdesInitialVector);
Array.Copy(datosEscribir, 8 + l_iAux, aux1, 0, 8);
Array.Copy(datosEscribir, l_iAux, aux2, 0, 8);
DesfireBarik.XorStr(ref aux1, ref aux2, 8);
res = criptoTransformDec2.TransformBlock(aux1, 0, 8, datosEscribir, 8 + l_iAux);
res = criptoTransformEnc2.TransformBlock(datosEscribir, 8 + l_iAux, 8, datosEscribir, 8 + l_iAux);
res = criptoTransformDec3.TransformBlock(datosEscribir, 8 + l_iAux, 8, datosEscribir, 8 + l_iAux);
l_iAux += 8;
}
private static void XorStr (ref byte[] str1, ref byte[] str2, int qty )
{
int i = 0;
for (i = 0; i < qty; i++ )
str1[i] = (byte)(str1[i] ^ str2[i]);
}

Categories

Resources