Various improvements to native cipher so that it now actually destroys Java in terms of speed. Closes #871 - thanks @ninja-
This commit is contained in:
parent
b3627652f2
commit
2e80bf30dd
@ -3,54 +3,66 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#define BYTE unsigned char
|
#define BYTE unsigned char
|
||||||
|
|
||||||
jlong Java_net_md_15_bungee_NativeCipherImpl_init
|
jlong Java_net_md_15_bungee_NativeCipherImpl_initKey
|
||||||
(JNIEnv* env, jobject obj, jbyteArray key)
|
(JNIEnv* env, jobject obj, jbyteArray key)
|
||||||
{
|
{
|
||||||
AES_KEY *aes_key = malloc(sizeof(AES_KEY));
|
AES_KEY *aes_key = malloc(sizeof(AES_KEY));
|
||||||
|
|
||||||
jboolean isKeyCopy;
|
jboolean isFieldCopy;
|
||||||
BYTE *key_bytes = (BYTE*)(*env)->GetByteArrayElements(env, key, &isKeyCopy);
|
BYTE *key_bytes = (BYTE*)(*env)->GetByteArrayElements(env, key, &isFieldCopy);
|
||||||
int key_length = (*env)->GetArrayLength(env, key) * 8; // in bits
|
int key_length = (*env)->GetArrayLength(env, key) * 8; // in bits
|
||||||
|
|
||||||
AES_set_encrypt_key(key_bytes, key_length, aes_key);
|
AES_set_encrypt_key(key_bytes, key_length, aes_key);
|
||||||
|
|
||||||
if (isKeyCopy) {
|
if (isFieldCopy) {
|
||||||
(*env)->ReleaseByteArrayElements(env, key, (jbyte*)key_bytes, JNI_ABORT);
|
(*env)->ReleaseByteArrayElements(env, key, (jbyte*)key_bytes, JNI_ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (long) aes_key;
|
return (long) aes_key;
|
||||||
}
|
}
|
||||||
|
jlong Java_net_md_15_bungee_NativeCipherImpl_initIV
|
||||||
|
(JNIEnv* env, jobject obj, jbyteArray iv)
|
||||||
|
{
|
||||||
|
jboolean isFieldCopy;
|
||||||
|
BYTE *iv_bytes = (BYTE*)(*env)->GetByteArrayElements(env, iv, &isFieldCopy);
|
||||||
|
int iv_length = (*env)->GetArrayLength(env, iv);
|
||||||
|
|
||||||
|
BYTE* jni_iv = malloc(iv_length);
|
||||||
|
|
||||||
|
memcpy(jni_iv, iv_bytes, iv_length);
|
||||||
|
|
||||||
|
if (isFieldCopy) {
|
||||||
|
(*env)->ReleaseByteArrayElements(env, iv, (jbyte*)iv_bytes, JNI_ABORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (long) jni_iv;
|
||||||
|
}
|
||||||
void Java_net_md_15_bungee_NativeCipherImpl_free
|
void Java_net_md_15_bungee_NativeCipherImpl_free
|
||||||
(JNIEnv* env, jobject obj, jlong key)
|
(JNIEnv* env, jobject obj, jlong key, jlong iv)
|
||||||
{
|
{
|
||||||
free((AES_KEY*)key);
|
free((AES_KEY*)key);
|
||||||
|
free((BYTE*)iv);
|
||||||
}
|
}
|
||||||
void Java_net_md_15_bungee_NativeCipherImpl_cipher
|
void Java_net_md_15_bungee_NativeCipherImpl_cipher
|
||||||
(JNIEnv* env, jobject obj, jboolean forEncryption, jlong key, jbyteArray iv, jlong in, jlong out, jint length)
|
(JNIEnv* env, jobject obj, jboolean forEncryption, jlong key, jlong iv, jlong in, jlong out, jint length)
|
||||||
{
|
{
|
||||||
AES_KEY *aes_key = (AES_KEY*)key;
|
AES_KEY *aes_key = (AES_KEY*)key;
|
||||||
|
|
||||||
size_t buffer_length = (size_t) length;
|
size_t buffer_length = (size_t) length;
|
||||||
|
|
||||||
BYTE *input = (BYTE*) in;
|
BYTE *input = (BYTE*) in;
|
||||||
BYTE *output = (BYTE*) out;
|
BYTE *output = (BYTE*) out;
|
||||||
|
BYTE* jni_iv = (BYTE*) iv;
|
||||||
jboolean isCopy;
|
|
||||||
BYTE *iv_bytes = (BYTE*)(*env)->GetByteArrayElements(env, iv, &isCopy);
|
|
||||||
|
|
||||||
AES_cfb8_encrypt(
|
AES_cfb8_encrypt(
|
||||||
input, // input buffer
|
input, // input buffer
|
||||||
output, // output buffer
|
output, // output buffer
|
||||||
buffer_length, // readable bytes
|
buffer_length, // readable bytes
|
||||||
aes_key, // encryption key
|
aes_key, // encryption key
|
||||||
iv_bytes, // IV
|
jni_iv, // IV
|
||||||
NULL, // not needed
|
NULL, // not needed
|
||||||
forEncryption ? AES_ENCRYPT : AES_DECRYPT // encryption mode
|
forEncryption ? AES_ENCRYPT : AES_DECRYPT // encryption mode
|
||||||
);
|
);
|
||||||
|
|
||||||
// IV has changed, let's copy it back
|
|
||||||
if (isCopy) {
|
|
||||||
(*env)->ReleaseByteArrayElements(env, iv, (jbyte*)iv_bytes, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,17 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Class: net_md_5_bungee_NativeCipherImpl
|
* Class: net_md_5_bungee_NativeCipherImpl
|
||||||
* Method: init
|
* Method: init_key
|
||||||
* Signature: ([B)J
|
* Signature: ([B)J
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_init
|
JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_initKey
|
||||||
|
(JNIEnv *, jobject, jbyteArray);
|
||||||
|
/*
|
||||||
|
* Class: net_md_5_bungee_NativeCipherImpl
|
||||||
|
* Method: init_iv
|
||||||
|
* Signature: ([B)J
|
||||||
|
*/
|
||||||
|
JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_initIV
|
||||||
(JNIEnv *, jobject, jbyteArray);
|
(JNIEnv *, jobject, jbyteArray);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -21,7 +28,7 @@ JNIEXPORT jlong JNICALL Java_net_md_15_bungee_NativeCipherImpl_init
|
|||||||
* Signature: (J)V
|
* Signature: (J)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_free
|
JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_free
|
||||||
(JNIEnv *, jobject, jlong);
|
(JNIEnv *, jobject, jlong, jlong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: net_md_5_bungee_NativeCipherImpl
|
* Class: net_md_5_bungee_NativeCipherImpl
|
||||||
@ -29,9 +36,10 @@ JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_free
|
|||||||
* Signature: (ZJ[BJJI)V
|
* Signature: (ZJ[BJJI)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_cipher
|
JNIEXPORT void JNICALL Java_net_md_15_bungee_NativeCipherImpl_cipher
|
||||||
(JNIEnv *, jobject, jboolean, jlong, jbyteArray, jlong, jlong, jint);
|
(JNIEnv *, jobject, jboolean, jlong, jlong, jlong, jlong, jint);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -16,13 +16,12 @@ public class NativeCipher implements BungeeCipher
|
|||||||
{
|
{
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final NativeCipherImpl nativeCipher = new NativeCipherImpl();
|
private final static NativeCipherImpl nativeCipher = new NativeCipherImpl();
|
||||||
private boolean forEncryption;
|
|
||||||
private byte[] iv;
|
|
||||||
/*============================================================================*/
|
|
||||||
private static boolean loaded;
|
private static boolean loaded;
|
||||||
|
/*============================================================================*/
|
||||||
private long pointer;
|
private boolean forEncryption;
|
||||||
|
private long keyPointer;
|
||||||
|
private long ivPointer;
|
||||||
|
|
||||||
public static boolean isSupported()
|
public static boolean isSupported()
|
||||||
{
|
{
|
||||||
@ -59,23 +58,18 @@ public class NativeCipher implements BungeeCipher
|
|||||||
@Override
|
@Override
|
||||||
public void init(boolean forEncryption, SecretKey key) throws GeneralSecurityException
|
public void init(boolean forEncryption, SecretKey key) throws GeneralSecurityException
|
||||||
{
|
{
|
||||||
if ( pointer != 0 )
|
nativeCipher.free( this.keyPointer, this.ivPointer );
|
||||||
{
|
|
||||||
nativeCipher.free( pointer );
|
|
||||||
}
|
|
||||||
this.forEncryption = forEncryption;
|
this.forEncryption = forEncryption;
|
||||||
this.iv = key.getEncoded(); // initialize the IV
|
|
||||||
this.pointer = nativeCipher.init( key.getEncoded() );
|
byte[] encoded = key.getEncoded();
|
||||||
|
this.keyPointer = nativeCipher.initKey( encoded );
|
||||||
|
this.ivPointer = nativeCipher.initIV( encoded );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void free()
|
public void free()
|
||||||
{
|
{
|
||||||
if ( pointer != 0 )
|
nativeCipher.free( keyPointer, ivPointer );
|
||||||
{
|
|
||||||
nativeCipher.free( pointer );
|
|
||||||
pointer = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -84,8 +78,8 @@ public class NativeCipher implements BungeeCipher
|
|||||||
// Smoke tests
|
// Smoke tests
|
||||||
in.memoryAddress();
|
in.memoryAddress();
|
||||||
out.memoryAddress();
|
out.memoryAddress();
|
||||||
Preconditions.checkState( pointer != 0, "Invalid pointer to AES key!" );
|
Preconditions.checkState( keyPointer != 0, "Invalid pointer to AES key!" );
|
||||||
Preconditions.checkState( iv != null, "Invalid IV!" );
|
Preconditions.checkState( ivPointer != 0, "Invalid pointer to IV!" );
|
||||||
|
|
||||||
// Store how many bytes we can cipher
|
// Store how many bytes we can cipher
|
||||||
int length = in.readableBytes();
|
int length = in.readableBytes();
|
||||||
@ -93,7 +87,7 @@ public class NativeCipher implements BungeeCipher
|
|||||||
out.ensureWritable( length );
|
out.ensureWritable( length );
|
||||||
|
|
||||||
// Cipher the bytes
|
// Cipher the bytes
|
||||||
nativeCipher.cipher( forEncryption, pointer, iv, in.memoryAddress() + in.readerIndex(), out.memoryAddress() + out.writerIndex(), length );
|
nativeCipher.cipher( forEncryption, keyPointer, ivPointer, in.memoryAddress() + in.readerIndex(), out.memoryAddress() + out.writerIndex(), length );
|
||||||
|
|
||||||
// Go to the end of the buffer, all bytes would of been read
|
// Go to the end of the buffer, all bytes would of been read
|
||||||
in.readerIndex( in.writerIndex() );
|
in.readerIndex( in.writerIndex() );
|
||||||
|
@ -9,24 +9,33 @@ class NativeCipherImpl
|
|||||||
* @param key the key to for encryption
|
* @param key the key to for encryption
|
||||||
* @return the pointer to key
|
* @return the pointer to key
|
||||||
*/
|
*/
|
||||||
native long init(byte[] key);
|
native long initKey(byte[] key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the iv.
|
||||||
|
*
|
||||||
|
* @param iv the iv
|
||||||
|
* @return the pointer to iv
|
||||||
|
*/
|
||||||
|
native long initIV(byte[] iv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the key.
|
* Frees the key.
|
||||||
*
|
*
|
||||||
* @param key the pointer to key
|
* @param key the pointer to key
|
||||||
|
* @param iv the pointer to iv
|
||||||
*/
|
*/
|
||||||
native void free(long key);
|
native void free(long key, long iv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will encrypt some data in AES-CFB8 using the specified key.
|
* This method will encrypt some data in AES-CFB8 using the specified key.
|
||||||
*
|
*
|
||||||
* @param forEncryption encryption / decryption mode
|
* @param forEncryption encryption / decryption mode
|
||||||
* @param key the pointer to key
|
* @param key the pointer to key
|
||||||
* @param iv the iv to use
|
* @param iv the pointer to iv
|
||||||
* @param in the starting memory address for reading data
|
* @param in the starting memory address for reading data
|
||||||
* @param out the starting memory address for writing data
|
* @param out the starting memory address for writing data
|
||||||
* @param length the length of data to read / write
|
* @param length the length of data to read / write
|
||||||
*/
|
*/
|
||||||
native void cipher(boolean forEncryption, long key, byte[] iv, long in, long out, int length);
|
native void cipher(boolean forEncryption, long key, long iv, long in, long out, int length);
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user