I'm trying to establish communication between a website and an Arduino. I need to authenticate all the messages from my website to the Arduino, so I have found that the less time expensive way is using XTEA cryptography.
My PHP code for the website is:
mcrypt_encrypt(MCRYPT_XTEA, 'qwertyuiasdfghjk', 'asdfasdf', MCRYPT_MODE_ECB);
where "qwertyuiasdfghjk" is a 128 bits key and "asdfasdf" is a 64 bits message.
On the Arduino side I'm using:
void _xtea_dec(void* dest, const void* v, const void* k)
{
uint8_t i;
uint32_t v0=((uint32_t*)v)[0], v1=((uint32_t*)v)[1];
uint32_t sum=0xC6EF3720, delta=0x9E3779B9;
for(i=0; i<32; i++)
{
v1 -= ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + ((uint32_t*)k)[sum>>11 & 3]);
sum -= delta;
v0 -= ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + ((uint32_t*)k)[sum & 3]);
}
((uint32_t*)dest)[0]=v0; ((uint32_t*)dest)[1]=v1;
}
where the parameters are:
char dest[9]; //Destination
char v[9]; //Encrypted message
char k[17]; //Key
but my decrypted message is far away from the original message... It still having 64 bits, but it is totally different...
What should I do?
(This is the first time that I ask a question here, usually I all my questions are solved somewhere in Stack Overflow...)
Most likely your cipher keys are different. Make sure they are the same in both ends.
C:
// "annoying monkey"
uint32_t key[4] = {0x6f6e6e61, 0x676e6979, 0x6e6f6d20, 0x0079656b };
PHP:
mcrypt_encrypt(MCRYPT_XTEA, 'annoying monkey', 'data', MCRYPT_MODE_ECB);
As far as I remember, the XTEA specification did not provide test vectors and your code does not seem to care about endianness. Most probably it is a matter of key or data assumed/being in the wrong endian. Look at the implementation of mcrypt_encrypt function in the PHP source.
Related
I'm trying to convert PHP code to C++.
$this->Key + 1 + log2p (floor($TimePlot/$this->kY)*M_PI-2*20
In PHP Key is string in C++ key2 is char*, timeplot is time_t and val is int.
key2 + 1 + log2(floor((double)timeplot/this->val*M_PI-2*20))
and the error is:
error C2111: '+' : pointer addition requires integral operand
I don't know what to do to make it working. Thanks in advance.
If your $this->key is string, and you want to end up with a string in C++ also, then you need to do something like this:
char bf[1024];
sprintf (bf, "%f", 1.0 + log2(floor((double)timeplot/this->val*M_PI-2*20)) );
std::string k = key2;
k += bf;
assuming everything else in your expression resolve to numeric values that can participate in numeric calculations. I used a buffer length of 1024 bytes here, you can adjust it accordingly.
I am using the below php code for encryption:
$enc_request = base64_encode(
mcrypt_encrypt(MCRYPT_RIJNDAEL_256,
$this->_app_key,
json_encode($request_params),
MCRYPT_MODE_ECB)
);
Now trying to encrypt the in android and getting the different encrypted string. Below is the android code:
public void enc(){
byte[] rawKey = getRawKey("my_key".getBytes());
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal("my_message".getBytes());
String result=Base64.encodeToString(encrypted, Base64.DEFAULT);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(256, sr);
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
Could any one help me, where I am wrong? And get same correct encrypted string in android too.
I've created a main method in Java using Bouncy Castle to show the inner workings of mcrypt_encrypt() used in your code sample.
This is mainly to show other developers that PHP's mcrypt_encrypt() is a very dangerous method to use. It won't fail much, but that is because it rather continues where it should have stopped long ago. For instance, it adds or removes values from the key. It emits a warning when it does do this, but it won't directly show in the code.
public static void main(String[] args) throws DataLengthException, IllegalStateException, InvalidCipherTextException {
// just some constants
boolean ENCRYPT = true;
boolean DECRYPT = false;
// the key is either in binary in PHP or a string (dynamic isn't it?), lets assume ASCII
byte[] givenKey = args[0].getBytes(Charset.forName("ASCII"));
// determine the key size dynamically, somebody thought this was a good idea...
// NOTE: PHP will emit a warning if the key size is larger, but will simply use the
// largest key size otherwise
final int keysize;
if (givenKey.length <= 128 / Byte.SIZE) {
keysize = 128;
} else if (givenKey.length <= 192 / Byte.SIZE) {
keysize = 192;
} else {
keysize = 256;
}
// create a 256 bit key by adding zero bytes to the decoded key
byte[] keyData = new byte[keysize / Byte.SIZE];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
KeyParameter key = new KeyParameter(keyData);
// create a Rijndael cipher with 256 bit block size, this is not AES
BlockCipher rijndael = new RijndaelEngine(256);
// use a padding method that only works on data that cannot end with zero valued bytes
ZeroBytePadding c = new ZeroBytePadding();
// use ECB mode encryption, which should never be used
PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(rijndael, c);
// initialize the cipher using the key (no need for an IV, this is ECB)
pbbc.init(ENCRYPT, key);
// create a plain text byte array
byte[] plaintext = args[1].getBytes(Charset.forName("UTF8"));
// create a buffer for the ciphertext
byte[] ciphertext = new byte[pbbc.getOutputSize(plaintext.length)];
int offset = 0;
offset += pbbc.processBytes(plaintext, 0, plaintext.length, ciphertext, offset);
offset += pbbc.doFinal(ciphertext, offset);
// show the ciphertext
System.out.println(new String(Hex.encode(ciphertext), Charset.forName("ASCII")));
// reverse the encryption
pbbc.init(DECRYPT, key);
byte[] decrypted = new byte[pbbc.getOutputSize(ciphertext.length)];
offset = 0;
offset += pbbc.processBytes(ciphertext, 0, ciphertext.length, decrypted, offset);
offset += pbbc.doFinal(decrypted, offset);
// this will probably print out correctly, but it isn't actually correct
System.out.println(new String(decrypted, Charset.forName("UTF8")));
// check out the zero's at the end
System.out.println(new String(Hex.encode(decrypted), Charset.forName("UTF8")));
// so lets make it a bit shorter... the PHP way
// note that in PHP, the string may *not* contain a null terminator
// add it yourself before printing the string
System.out.println(new String(decrypted, Charset.forName("UTF8")).replaceAll("\\x00+$", ""));
}
Warning: the above code contains ZeroBytePadding. I later discovered that there is a difference between Bouncy Castle and PHP in this respect: Bouncy Castle expects that you always have to pad, while PHP doesn't. So Bouncy adds 1..n bytes while PHP adds 0..(n-1) bytes, where n is the block size (32 bytes for Rijndael-256/256). So you may have to do the padding/unpadding yourself; be sure to test the edge cases!
Hey all so I've ran into a bit of a problem, from PHP I have to read some data from a binary file where SPACE is of the utmost importance so they've used 24 bit integers in places.
Now for most of the data I can read with unpack however pack/unpack does not support 24 bit int's :s
I thought I could perhaps simple read the data (say for example 000104) as H* and have it read into a var that would be correct.
// example binary data say I had the following 3 bytes in a binary file
// 0x00, 0x01, 0x04
$buffer = unpack("H*", $data);
// this should equate to 260 in base 10 however unpacking as H* will not get
// this value.
// now we can't unpack as N as it requires 0x4 bytes of data and n being a 16 bit int
// is too short.
Has anyone had to deal with this before? Any solutions? advice?
If the file has only 3 bytes as above, the easiest way is padding as #DaveRandom said. But if it's a long file this method becomes inefficient.
In this case you can read each element as a char and a short, after that repack it by bitwise operators.
Or you can read along 12 bytes as 3 longs and then splits it into 4 groups of 3 bytes with bitwise operators. The remaining bytes will be extracted by the above 2 methods. This will be the fastest solution on large data.
unsigned int i, j;
unsigned int dataOut[SIZE];
for (i = 0, j = 0; j < size; i += 4, j += 3)
{
dataOut[i] = dataIn[j] >> 8;
dataOut[i + 1] = ((dataIn[j] & 0xff) << 16) | (dataIn[j + 1] >> 16);
dataOut[i + 2] = ((dataIn[j + 1] & 0xffff) << 8) | (dataIn[j + 2] >> 24);
dataOut[i + 3] = dataIn[j + 2] & 0xffffff;
}
The following question has an example code to unpack a string of 24/48bits too
I have some C++ code (segment seen below), I need to convert this to another language (namely PHP). The code, as seen, uses structs, which PHP doesn't do. I know I can "kind of" emulate structs through objects/arrays, however, this isn't the same. That is not my main problem though. I need a way to implement the sizeof() function found in C++ (since PHP's sizeof() function just counts the number of elements in an array/object).
typedef unsigned long Offset;
typedef unsigned long Size;
struct Location {
Offset offset;
Size size;
};
struct Header {
unsigned long magic;
unsigned long version;
struct Location elements;
struct Location ids;
struct Location strings;
struct Location integers;
struct Location decimals;
struct Location files;
};
int Build() {
Header theheader;
theheader.magic = *((unsigned long*)"P3TF");
theheader.version = 272;
theheader.elements.offset = sizeof(theheader);
theheader.elements.size = element_offset;
theheader.ids.offset = ((theheader.elements.offset + theheader.elements.size + 15) / 16) * 16;
theheader.ids.size = ids_offset;
theheader.strings.offset = ((theheader.ids.offset + theheader.ids.size + 15) / 16) * 16;
theheader.strings.size = string_offset;
theheader.integers.offset = ((theheader.strings.offset + theheader.strings.size + 15) / 16) * 16;
theheader.integers.size = 0;
theheader.decimals.offset = ((theheader.integers.offset + theheader.integers.size + 15) / 16) * 16;
theheader.decimals.size = 0;
theheader.files.offset = ((theheader.decimals.offset + theheader.decimals.size + 15) / 16) * 16;
theheader.files.size = file_offset;
theheader.padding[0] = 0;
theheader.padding[1] = 0;
fwrite(&theheader, 1, sizeof(theheader), file_handle);
}
Can anyone please point me in the right direction on how to do this?
Any help would be appreciated.
Obviously recreating sizeof from C will be a difficult feat, as C is statically-typed and, traditionally, sizeof is evaluated at run-time by the compiler. PHP is also pretty quiet about its memory usage.
One method of dynamically grabbing the size of an object is to use memory_get_usage (official PHP reference) before and after the allocation of the object in question. Of course, you'll run into some fun calculations when you compare the two memory usage values, as storing the values into variables will allocate memory also.
This is a pretty shaky method of recreating sizeof, but if it works it works.
You could simply sum all sizes of the objects in the array or object. However, that still only gets the length of strings, etc. If you want the actual size of the binary representation of the object, you'll have to do some additional math, such as converting all ints to 32 bits (or 64) and appending a null byte to all UTF-8 strings. If you're using charsets, do make sure that they are single-byte or at least measurable in bytes.
PHP does not have a function that checks the memory size of an object.
The Zend_Amf specification states that a Number type returned from flash will map to a float in PHP. Fine. But why does the number 16 get returned as 6.1026988574311E_320 ? PHP version is 5.2.9 running on OS X.
I have tried forcing a cast to integer in PHP (the above value gets rounded to 0) and also from Actionscript using int(16) - the latter comes through as NULL. How can ensure that Flash returns an integer via AMF and that PHP can deal with it?
You have a classic endian problem. Looks like either Zend or flash is doing the wrong thing with the endianness of this double. Here is the a program that prints the double (and its hex value). It then reverses the endianness and prints it again.
#include <stdio.h>
#include <stdint.h>
int main(void)
{
double d = 16;
uint32_t *i = (uint32_t *)(&d);
uint8_t *c = (uint8_t *)(&d);
size_t j;
printf("%08x %08x %lg\n", i[1], i[0], d);
for(j = 0; j < sizeof(double) / 2; j++)
{
uint8_t tmp;
tmp = c[j];
c[j] = c[sizeof(double) - j - 1];
c[sizeof(double) - j - 1] = tmp;
}
printf("%08x %08x %lg\n", i[1], i[0], d);
return 0;
}
On an Intel (little endian processor), you get this output
40300000 00000000 16
00000000 00003040 6.1027e-320
Are you perhaps running this on a PPC Mac (big endian)? Seems like one of your tools is not doing the right thing on your architecture. File a bug with the vendors.
As a hacky workaround, I suggest turning your number into a string and then converting it back to a double on the other end.
I don't know entirely what is going wrong in your situation, but I think I may be able to partially illuminate what is happening to your code. I ran the following quick hack to test a theory:
void hexdump_double(double dbl)
{
assert(8 == sizeof(dbl));
printf("double: %02X %02X %02X %02X %02X %02X %02X %02X (%lg)\n",
((char *)&(dbl))[0],
((char *)&(dbl))[1],
((char *)&(dbl))[2],
((char *)&(dbl))[3],
((char *)&(dbl))[4],
((char *)&(dbl))[5],
((char *)&(dbl))[6],
((char *)&(dbl))[7],
dbl);
}
int main()
{
hexdump_double(6.1026988574311E-320);
}
Which produces some exciting output:
double: 40 30 00 00 00 00 00 00 (6.1027e-320)
As you can see, that little floating-point number isn't any random pattern of bits. However, it also doesn't look to be related to "16."
Where Zend_Amf documentation states that ActionScript Number type is returned as a PHP float, what is meant is the class Number documented by Adobe: Adobe.com Flex documentation. It does not mean that any "number" will be passed as a double.
An int with value less than 2^29 will be returned transmitted in AMF as an integer type, and I assume Zend_Amf will return this as an integer.
How are you transmitting the AMF object from your ActionScript? Is it feasible to dump the bytes being sent?