mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Implement native AES cipher.
This commit is contained in:
@@ -4,10 +4,12 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := final-key
|
||||
|
||||
LOCAL_SRC_FILES := final_key.c
|
||||
LOCAL_SRC_FILES := final_key.c aes.c
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../openssl-0.9.8l/include
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := openssl-crypto
|
||||
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
138
jni/final_key/aes.c
Normal file
138
jni/final_key/aes.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "KeePassDroidNative", __VA_ARGS__)
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "KeePassDroidNative", __VA_ARGS__)
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "KeePassDroidNative", __VA_ARGS__)
|
||||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "KeePassDroidNative", __VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "KeePassDroidNative", __VA_ARGS__)
|
||||
|
||||
jlong Java_com_keepassdroid_crypto_NativeAESCipherSpi_nativeInit(JNIEnv *env,
|
||||
jobject this, jboolean encrypt, jbyteArray key, jbyteArray iv,
|
||||
jboolean padding) {
|
||||
|
||||
LOGV("1");
|
||||
// Convert keys to c
|
||||
jsize key_len = (*env)->GetArrayLength(env, key);
|
||||
char *c_key = (char *) malloc(key_len);
|
||||
(*env)->GetByteArrayRegion(env, key, 0, key_len, c_key);
|
||||
LOGV("2: Keylen: %d", key_len);
|
||||
|
||||
|
||||
// Covert iv to c
|
||||
jsize iv_len = (*env)->GetArrayLength(env, iv);
|
||||
char *c_iv = (char *) malloc(iv_len);
|
||||
(*env)->GetByteArrayRegion(env, iv, 0, iv_len, c_iv);
|
||||
LOGV("3: IvLen: %d", iv_len);
|
||||
|
||||
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *) malloc(sizeof(EVP_CIPHER_CTX));
|
||||
LOGV("3.5: %d", sizeof(EVP_CIPHER_CTX));
|
||||
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, c_key, c_iv, encrypt);
|
||||
|
||||
LOGV("4");
|
||||
if ( padding ) {
|
||||
EVP_CIPHER_CTX_set_padding(ctx, 1);
|
||||
} else {
|
||||
EVP_CIPHER_CTX_set_padding(ctx, 0);
|
||||
}
|
||||
|
||||
LOGV("5");
|
||||
// Free allocated memory
|
||||
free(c_iv);
|
||||
free(c_key);
|
||||
|
||||
LOGV("6: ctxPtr=%d",ctx);
|
||||
|
||||
return (jlong) ctx;
|
||||
}
|
||||
|
||||
void Java_com_keepassdroid_crypto_NativeAESCipherSpi_nativeCleanup(JNIEnv *env,
|
||||
jobject this, jlong ctxPtr) {
|
||||
|
||||
LOGV("cleanup");
|
||||
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *) ctxPtr;
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(ctx);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
jint Java_com_keepassdroid_crypto_NativeAESCipherSpi_nativeUpdate(JNIEnv *env,
|
||||
jobject this, jlong ctxPtr, jbyteArray input, jint inputOffset,
|
||||
jint inputLen, jbyteArray output, jint outputOffset, jint outputSize) {
|
||||
|
||||
|
||||
LOGV("InputSize: %d; OutputSize: %d", inputLen, outputSize);
|
||||
if ( inputLen == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *c_input = (char *) malloc(inputLen);
|
||||
|
||||
(*env)->GetByteArrayRegion(env, input, inputOffset, inputLen, c_input);
|
||||
|
||||
int outLen;
|
||||
char *c_output;
|
||||
|
||||
// Worst case is all full blocks with 1 byte on the left and right
|
||||
//int max_update_size = (((inputLen - 2) / AES_BLOCK_SIZE) + 2) * AES_BLOCK_SIZE;
|
||||
c_output = (char *) malloc(outputSize);
|
||||
|
||||
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *) ctxPtr;
|
||||
LOGV("Pre: ctxPtr=%d", ctx);
|
||||
EVP_CipherUpdate(ctx, c_output, &outLen, c_input, inputLen);
|
||||
LOGV("Post");
|
||||
|
||||
/* output can differ on final
|
||||
if ( outLen != ((int) outputSize) ) {
|
||||
LOGV("Outsize differs: %d", outLen);
|
||||
free(c_output);
|
||||
free(c_input);
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
LOGV("PreOut: OutLen=%d", outLen);
|
||||
(*env)->SetByteArrayRegion(env, output, outputOffset, outLen, c_output);
|
||||
|
||||
free(c_output);
|
||||
free(c_input);
|
||||
LOGV("PostOut");
|
||||
|
||||
|
||||
|
||||
return (jint) outLen; // I think jint should always be bigger than int
|
||||
|
||||
}
|
||||
|
||||
jint Java_com_keepassdroid_crypto_NativeAESCipherSpi_nativeDoFinal(JNIEnv *env,
|
||||
jobject this, jlong ctxPtr, jbyteArray output, jint outputOffset,
|
||||
jint outputSize) {
|
||||
|
||||
LOGV("outputOffset=%d", outputOffset);
|
||||
char *c_output = (char *) malloc(outputSize);
|
||||
|
||||
int outLen;
|
||||
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *) ctxPtr;
|
||||
EVP_CipherFinal_ex(ctx, c_output, &outLen);
|
||||
|
||||
/*
|
||||
if ( outLen != ((int) outputSize) ) {
|
||||
free(c_output);
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
LOGV("Final: OutputLen=%d, outputOffset=%d", outLen, (int)outputOffset);
|
||||
|
||||
(*env)->SetByteArrayRegion(env, output, outputOffset, outLen, c_output);
|
||||
|
||||
free(c_output);
|
||||
|
||||
return (jint) outLen;
|
||||
|
||||
}
|
||||
255
src/com/keepassdroid/crypto/NativeAESCipherSpi.java
Normal file
255
src/com/keepassdroid/crypto/NativeAESCipherSpi.java
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright 2009 Brian Pellin.
|
||||
*
|
||||
* This file is part of KeePassDroid.
|
||||
*
|
||||
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDroid is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.keepassdroid.crypto;
|
||||
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.InvalidParameterSpecException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherSpi;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
public class NativeAESCipherSpi extends CipherSpi {
|
||||
|
||||
private final int AES_BLOCK_SIZE = 16;
|
||||
private byte[] mIV;
|
||||
|
||||
private boolean mIsInited = false;
|
||||
private boolean mEncrypting = false;
|
||||
private long mCtxPtr;
|
||||
|
||||
private int mBuffered;
|
||||
private boolean mPadding = false;
|
||||
|
||||
@Override
|
||||
protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
|
||||
throws IllegalBlockSizeException, BadPaddingException {
|
||||
int maxSize = engineGetOutputSize(inputLen);
|
||||
byte[] output = new byte[maxSize];
|
||||
|
||||
int finalSize = doFinal(input, inputOffset, inputLen, output, 0);
|
||||
|
||||
if ( maxSize == finalSize ) {
|
||||
return output;
|
||||
} else {
|
||||
// TODO: Special doFinal to avoid this copy
|
||||
byte[] exact = new byte[finalSize];
|
||||
System.arraycopy(output, 0, exact, 0, finalSize);
|
||||
return exact;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
|
||||
byte[] output, int outputOffset) throws ShortBufferException,
|
||||
IllegalBlockSizeException, BadPaddingException {
|
||||
|
||||
int result = doFinal(input, inputOffset, inputLen, output, outputOffset);
|
||||
|
||||
if ( result == -1 ) {
|
||||
throw new ShortBufferException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
|
||||
mBuffered = 0;
|
||||
|
||||
int outputSize = engineGetOutputSize(inputLen);
|
||||
|
||||
int updateAmt = nativeUpdate(mCtxPtr, input, inputOffset, inputLen, output, outputOffset, outputSize);
|
||||
|
||||
int finalAmt = nativeDoFinal(mCtxPtr, output, outputOffset + updateAmt, outputSize - updateAmt);
|
||||
|
||||
return updateAmt + finalAmt;
|
||||
}
|
||||
|
||||
private native int nativeDoFinal(long ctxPtr, byte[] output, int outputOffest, int outputSize);
|
||||
|
||||
@Override
|
||||
protected int engineGetBlockSize() {
|
||||
return AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] engineGetIV() {
|
||||
return mIV;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int engineGetOutputSize(int inputLen) {
|
||||
int totalLen = mBuffered + inputLen;
|
||||
|
||||
if ( ! mPadding || ! mEncrypting ) {
|
||||
return totalLen;
|
||||
}
|
||||
|
||||
int padLen = AES_BLOCK_SIZE - (totalLen % AES_BLOCK_SIZE);
|
||||
|
||||
// TODO: Round up to nearest full block (there's probably a better way to do this)
|
||||
return totalLen + padLen;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AlgorithmParameters engineGetParameters() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
|
||||
byte[] ivArray = new byte[16];
|
||||
random.nextBytes(ivArray);
|
||||
|
||||
init(opmode, key, new IvParameterSpec(ivArray));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key,
|
||||
AlgorithmParameterSpec params, SecureRandom random)
|
||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
|
||||
IvParameterSpec ivparam;
|
||||
|
||||
if ( params instanceof IvParameterSpec ) {
|
||||
ivparam = (IvParameterSpec) params;
|
||||
} else {
|
||||
throw new InvalidAlgorithmParameterException("params must be an IvParameterSpec.");
|
||||
}
|
||||
|
||||
init(opmode, key, ivparam);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
|
||||
SecureRandom random) throws InvalidKeyException,
|
||||
InvalidAlgorithmParameterException {
|
||||
|
||||
try {
|
||||
engineInit(opmode, key, params.getParameterSpec(AlgorithmParameterSpec.class), random);
|
||||
} catch (InvalidParameterSpecException e) {
|
||||
throw new InvalidAlgorithmParameterException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void init(int opmode, Key key, IvParameterSpec params) {
|
||||
if ( mIsInited ) {
|
||||
cleanup();
|
||||
NativeLib.init();
|
||||
}
|
||||
|
||||
mIV = params.getIV();
|
||||
mEncrypting = opmode == Cipher.ENCRYPT_MODE;
|
||||
mBuffered = 0;
|
||||
mCtxPtr = nativeInit(mEncrypting, key.getEncoded(), mIV, mPadding);
|
||||
}
|
||||
|
||||
private native long nativeInit(boolean encrypt, byte[] key, byte[] iv, boolean mPadding);
|
||||
|
||||
private void cleanup() {
|
||||
nativeCleanup(mCtxPtr);
|
||||
|
||||
mCtxPtr = 0;
|
||||
}
|
||||
|
||||
private native void nativeCleanup(long ctxPtr);
|
||||
|
||||
@Override
|
||||
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
|
||||
if ( ! mode.equals("CBC") ) {
|
||||
throw new NoSuchAlgorithmException("This only supports CBC mode");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineSetPadding(String padding)
|
||||
throws NoSuchPaddingException {
|
||||
|
||||
if ( ! mIsInited ) {
|
||||
NativeLib.init();
|
||||
}
|
||||
|
||||
if ( padding.length() == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! padding.equals("PKCS5Padding") ) {
|
||||
throw new NoSuchPaddingException("Only supports PKCS5Padding.");
|
||||
}
|
||||
|
||||
mPadding = true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
|
||||
int maxSize = engineGetOutputSize(inputLen);
|
||||
byte output[] = new byte[maxSize];
|
||||
|
||||
int updateSize = update(input, inputOffset, inputLen, output, 0);
|
||||
|
||||
if ( updateSize == maxSize ) {
|
||||
return output;
|
||||
} else {
|
||||
// TODO: We could optimize update for this case to avoid this extra copy
|
||||
byte[] exact = new byte[updateSize];
|
||||
System.arraycopy(output, 0, exact, 0, updateSize);
|
||||
return exact;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
|
||||
byte[] output, int outputOffset) throws ShortBufferException {
|
||||
|
||||
int result = update(input, inputOffset, inputLen, output, outputOffset);
|
||||
|
||||
if ( result == -1 ) {
|
||||
throw new ShortBufferException("Insufficient buffer.");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
|
||||
mBuffered = (mBuffered + inputLen) % AES_BLOCK_SIZE;
|
||||
return nativeUpdate(mCtxPtr, input, inputOffset, inputLen, output, outputOffset, engineGetOutputSize(inputLen));
|
||||
}
|
||||
|
||||
private native int nativeUpdate(long ctxPtr, byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset, int outputSize);
|
||||
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public class AndroidFinalKey extends FinalKey {
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(pKeySeed, "AES"));
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IOException("InvalidKeyException: " + e.getMessage());
|
||||
throw new IOException("InvalidPasswordException: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Encrypt key rounds times
|
||||
|
||||
84
tests/src/com/keepassdroid/tests/crypto/AESTest.java
Normal file
84
tests/src/com/keepassdroid/tests/crypto/AESTest.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2009 Brian Pellin.
|
||||
*
|
||||
* This file is part of KeePassDroid.
|
||||
*
|
||||
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDroid is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.keepassdroid.tests.crypto;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.keepassdroid.crypto.finalkey.AESProvider;
|
||||
|
||||
public class AESTest extends TestCase {
|
||||
|
||||
private Random mRand = new Random();
|
||||
|
||||
public void testEncrypt() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
|
||||
// Test above below and at the blocksize
|
||||
testFinal(15);
|
||||
testFinal(16);
|
||||
testFinal(17);
|
||||
|
||||
// Test random larger sizes
|
||||
int size = mRand.nextInt(494) + 18;
|
||||
testFinal(size);
|
||||
}
|
||||
|
||||
private void testFinal(int dataSize) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
|
||||
// Generate some input
|
||||
byte[] input = new byte[dataSize];
|
||||
mRand.nextBytes(input);
|
||||
|
||||
// Generate key
|
||||
byte[] keyArray = new byte[32];
|
||||
mRand.nextBytes(keyArray);
|
||||
SecretKeySpec key = new SecretKeySpec(keyArray, "AES");
|
||||
|
||||
// Generate IV
|
||||
byte[] ivArray = new byte[16];
|
||||
mRand.nextBytes(ivArray);
|
||||
IvParameterSpec iv = new IvParameterSpec(ivArray);
|
||||
|
||||
Cipher android = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
android.init(Cipher.ENCRYPT_MODE, key, iv);
|
||||
byte[] outAndroid = android.doFinal(input, 0, dataSize);
|
||||
|
||||
AESProvider prov = new AESProvider();
|
||||
Cipher nat = Cipher.getInstance("AES/CBC/PKCS5Padding", prov);
|
||||
nat.init(Cipher.ENCRYPT_MODE, key, iv);
|
||||
byte[] outNative = nat.doFinal(input, 0, dataSize);
|
||||
|
||||
assertArrayEquals("Arrays differ on size: " + dataSize, outAndroid, outNative);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
80
tests/src/com/keepassdroid/tests/crypto/FinalKeyTest.java
Normal file
80
tests/src/com/keepassdroid/tests/crypto/FinalKeyTest.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2009 Brian Pellin.
|
||||
*
|
||||
* This file is part of KeePassDroid.
|
||||
*
|
||||
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDroid is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.keepassdroid.tests.crypto;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.keepassdroid.crypto.finalkey.AndroidFinalKey;
|
||||
import com.keepassdroid.crypto.finalkey.NativeFinalKey;
|
||||
|
||||
public class FinalKeyTest extends TestCase {
|
||||
private Random mRand;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mRand = new Random();
|
||||
}
|
||||
|
||||
public void testReflect() {
|
||||
boolean available = NativeFinalKey.availble();
|
||||
assertTrue("NativeFinalKey library cannot be loaded", available);
|
||||
|
||||
byte[] key = new byte[32];
|
||||
mRand.nextBytes(key);
|
||||
|
||||
byte[] out = NativeFinalKey.reflect(key);
|
||||
|
||||
assertArrayEquals("Array not reflected correctly", key, out);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testNativeAndroid() throws IOException {
|
||||
// Test both an old and an even number to test my flip variable
|
||||
testNativeFinalKey(5);
|
||||
testNativeFinalKey(6);
|
||||
}
|
||||
|
||||
private void testNativeFinalKey(int rounds) throws IOException {
|
||||
byte[] seed = new byte[32];
|
||||
byte[] key = new byte[32];
|
||||
byte[] nativeKey;
|
||||
byte[] androidKey;
|
||||
|
||||
mRand.nextBytes(seed);
|
||||
mRand.nextBytes(key);
|
||||
|
||||
AndroidFinalKey aKey = new AndroidFinalKey();
|
||||
androidKey = aKey.transformMasterKey(seed, key, rounds);
|
||||
|
||||
NativeFinalKey nKey = new NativeFinalKey();
|
||||
nativeKey = nKey.transformMasterKey(seed, key, rounds);
|
||||
|
||||
assertArrayEquals("Does not match", androidKey, nativeKey);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user