您的位置:首页 > 其它

通过JNI调用LibTEA 加密算法

2015-11-11 17:23 232 查看
最近在做的项目的传输系统上使用了TEA加密,采集端使用Java,但是说实在的换了多少个版本的Java实现都不能正确解密。。。

先简单介绍下TEA,据说QQ也在用。

TEA(Tiny Encryption Algorithm) 是一种简单高效的加密算法,以加密解密速度快,实现简单著称。算法真的很简单,TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。目前我只知道QQ一直用的是16轮TEA。没什么好说的,先给出C语言的源代码(默认是32轮)。

C语言实现:

tea_encrypt.h

#include <stdint.h>

/*void encrypt(uint32_t v[], uint32_t k[]);
void decrypt(uint32_t v[], uint32_t k[]);*/

extern void encrypt(uint32_t v[]);
extern void decrypt(uint32_t v[]);


tea_encrypt.c

#include "tea_encrypt.h"

static uint32_t tea_keys[4] = {0x2B6D5E6D, 0x24AAB7C3, 0x0E3E55F0, 0x21241BA9};

/*void encrypt(uint32_t v[], uint32_t k[])*/
void encrypt(uint32_t v[])
{
uint32_t v0 = v[0], v1 = v[1], sum = 0, i = 0;        /* set up */
uint32_t delta = 0x9E378198;                          /* a key schedule constent */
uint32_t k0 = tea_keys[0], k1 = tea_keys[1], k2 = tea_keys[2], k3 = tea_keys[3];  /* cache key*/

for(i=0; i<32; i++)
{
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
/* end cycle */
}

v[0] = v0;
v[1] = v1;
}

/*void decrypt(uint32_t v[], uint32_t k[])*/
void decrypt(uint32_t v[])
{
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6F03300, i = 0;  /* set up */
uint32_t delta = 0x9E378198;                             /* a key schedule */
uint32_t k0 = tea_keys[0], k1 = tea_keys[1], k2 = tea_keys[2], k3 = tea_keys[3];     /* cache key*/
sum = delta << 5;

for(i=0; i<32; i++)
{
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}

v[0] = v0;
v[1] = v1;
}


0、写个Java的native类

public class TeaJniNative {

static {
System.loadLibrary("libtea_native");
}

public native byte[] encrypt(byte[] v);
public native byte[] decrypt(byte[] v);

}


1、生成C语言的头文件

javac TeaJniNative.java
javah TeaJniNative


/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TeaJniNative */

#ifndef _Included_TeaJniNative
#define _Included_TeaJniNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     TeaJniNative
* Method:    encrypt
* Signature: ([B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_TeaJniNative_encrypt
(JNIEnv *, jobject, jbyteArray);

/*
* Class:     com_liuxiaobai_TeaJniNative
* Method:    decrypt
* Signature: ([B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_TeaJniNative_decrypt
(JNIEnv *, jobject, jbyteArray);

#ifdef __cplusplus
}
#endif
#endif


2、实现TeaJniNative.h方法,调用tea_encrypt.h的加密解密方法

/* Replace "dll.h" with the name of your header */
#include "TeaJniNative.h"
#include "tea_encrypt.h"

JNIEXPORT jbyteArray JNICALL Java_TeaJniNative_encrypt
(JNIEnv *env, jobject obj, jbyteArray input)
{
jbyte *pJbyte = (*env)->GetByteArrayElements(env, input, JNI_FALSE);
jsize len = (*env)->GetArrayLength(env, input);

uint8_t *v = (uint8_t *)pJbyte;

uint32_t offset;
for(offset = 0;(offset + 8) <= len;offset += 8)
{
encrypt((uint32_t *)(v + offset));
}

jbyteArray output = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(env, output, 0, len, pJbyte);

return output;
}

JNIEXPORT jbyteArray JNICALL Java_TeaJniNative_decrypt
(JNIEnv *env, jobject obj, jbyteArray input)
{
jbyte *pJbyte = (*env)->GetByteArrayElements(env, input, JNI_FALSE);
jsize len = (*env)->GetArrayLength(env, input);

uint8_t *v = (uint8_t *)pJbyte;

uint32_t offset;
for(offset = 0;(offset + 8) <= len;offset += 8)
{
decrypt((uint32_t *)(v + offset));
}

jbyteArray output = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(env, output, 0, len, pJbyte);

return output;

}


3、gcc编译生成.so,将该文件目录加入LD_LIBRARY_PATH中

gcc -m64 -fPIC -c src/TeaJniNative.c -o src/TeaJniNative.o -I/opt/develop_tools/jdk1.7.0_79/include -I/opt/develop_tools/jdk1.7.0_79/include/linux -DBUILDING_DLL=1
gcc -m64 -fPIC -c src/tea_encrypt.c -o src/tea_encrypt.o -I/opt/develop_tools/jdk1.7.0_79/include -I/opt/develop_tools/jdk1.7.0_79/include/linux -DBUILDING_DLL=1
gcc -m64 -shared src/TeaJniNative.o src/tea_encrypt.o -o libtea_native.so


Ex:

public class Main {

public static void main(String[] args) {
TeaJniNative tea = new TeaJniNative();

byte[] res0 = new byte[]{
0x00, 0x30, 0x30, 0x30, 0x43, 0x32, 0x39, 0x10
};
int i;
for(i = 0; i < res0.length; i++){
System.out.printf("[%02X]", res0[i]);
}
System.out.println();

byte[] res1 = tea.encrypt(res0);
for(i = 0; i < res1.length; i++){
System.out.printf("[%02X]", res1[i]);
}
System.out.println();

byte[] res2 = tea.decrypt(res1);
for(i = 0; i < res2.length; i++){
System.out.printf("[%02X]", res2[i]);
}
System.out.println();

}
}


Output:

[00][30][30][30][43][32][39][10]
[1B][01][2F][7F][DF][7B][3D][C2]
[00][30][30][30][43][32][39][10]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: