Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.idea

8 changes: 7 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

UNRELEASED - 2020-10-04
------------------
- Unified native I/O to hex strings ;
- Added other encoding methods : 'legacy' which behaves like v1.1.2, 'hex', 'base64' and 'buffer'
- Update example with tests for a range of test vectors

1.1.2 - 2019-12-20
------------------

Expand All @@ -17,4 +23,4 @@ Changelog
[danh]

- Update iOS config.
[maddijoyce]
[maddijoyce]
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@ This plugin is for use with React Native and allows your application to use scry
```javascript
import scrypt from 'react-native-scrypt';

// passwd must be a string
// salt must be an array of bytes integers
// With 'legacy' encoding (default): passwd must be a string, salt must be an array of bytes integers
// With 'hex' encoding: passwd and salt must be string encoded in hexadecimal
// With 'base64' encoding: passwd and salt must be string encoded in base64
// With 'buffer' encoding: passwd and salt must be Buffers (in the sense of [`buffer`](https://github.com/feross/buffer/) package)
// see example/App.js

const result = await scrypt(passwd, salt[, N=16384, r=8, p=1, dkLen=64])

const result = await scrypt(passwd, salt[, N=16384, r=8, p=1, dkLen=64, encoding='legacy'])
```

## LICENSE
Expand Down
67 changes: 33 additions & 34 deletions android/src/main/java/com/crypho/scrypt/RNScryptModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,60 +13,59 @@ public class RNScryptModule extends ReactContextBaseJavaModule {
System.loadLibrary("scrypt_jni");
}

private static final char[] HEX = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
private static final char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
private final ReactApplicationContext reactContext;
private static final String SCRYPT_ERROR = "Failure in scrypt";

public native byte[] scryptBridgeJNI(byte[] pass, char[] salt, Integer N, Integer r, Integer p, Integer dkLen);
public native byte[] scryptBridgeJNI(byte[] pass, byte[] salt, Integer N, Integer r, Integer p, Integer dkLen);

public RNScryptModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}


@ReactMethod
public void scrypt(
String passwd,
ReadableArray salt,
Integer N,
Integer r,
Integer p,
Integer dkLen,
Promise promise) {
try {
final byte[] passwordBytes = passwd.getBytes("UTF-8");
final char[] ssalt = getSalt(salt);
byte[] res = scryptBridgeJNI(passwordBytes, ssalt, N, r, p, dkLen);
String result = hexify(res);
promise.resolve(result);
} catch (Exception e) {
promise.reject(SCRYPT_ERROR, e);
}
String passwd,
String salt,
Integer N,
Integer r,
Integer p,
Integer dkLen,
Promise promise) {
try {
final byte[] passwordBytes = hexStringToByteArray(passwd);
final byte[] ssalt = hexStringToByteArray(salt);
byte[] res = scryptBridgeJNI(passwordBytes, ssalt, N, r, p, dkLen);
String result = hexify(res);
promise.resolve(result);
} catch (Exception e) {
promise.reject(SCRYPT_ERROR, e);
}
}

private String hexify (byte[] input) {
int len = input.length;
char[] result = new char[2 * len];
for ( int j = 0; j < len; j++ ) {
int v = input[j] & 0xFF;
result[j * 2] = HEX[v >>> 4];
result[j * 2 + 1] = HEX[v & 0x0F];
private static String hexify(byte[] input) {
int len = input.length;
char[] result = new char[2 * len];
for (int j = 0; j < len; j++) {
int v = input[j] & 0xFF;
result[j * 2] = HEX[v >>> 4];
result[j * 2 + 1] = HEX[v & 0x0F];
}
return new String(result).toLowerCase();
}

private char[] getSalt(ReadableArray src){
int s = src.size();
char[] result = new char[s];
for (int i = 0; i < s ; i++) {
result[i] = (char) src.getInt(i);
private static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return result;
return data;
}

@Override
public String getName() {
return "RNScrypt";
}
}
}
23 changes: 5 additions & 18 deletions android/src/main/jni/libscrypt-jni.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static void throwException(JNIEnv* env, char *msg);

JNIEXPORT jbyteArray JNICALL
Java_com_crypho_scrypt_RNScryptModule_scryptBridgeJNI( JNIEnv* env, jobject thiz,
jbyteArray pass, jcharArray salt, jobject N, jobject r, jobject p, jobject dkLen)
jbyteArray pass, jbyteArray salt, jobject N, jobject r, jobject p, jobject dkLen)
{
int i;
char *msg_error;
Expand All @@ -31,13 +31,13 @@ Java_com_crypho_scrypt_RNScryptModule_scryptBridgeJNI( JNIEnv* env, jobject thiz

jint passLen = (*env)->GetArrayLength(env, pass);
if((*env)->ExceptionOccurred(env)) {
LOGE("Failed to get passphrase lenght.");
LOGE("Failed to get passphrase length.");
goto END;
}

jint saltLen = (*env)->GetArrayLength(env, salt);
if((*env)->ExceptionOccurred(env)) {
LOGE("Failed to get salt lenght.");
LOGE("Failed to get salt length.");
goto END;
}

Expand All @@ -47,20 +47,12 @@ Java_com_crypho_scrypt_RNScryptModule_scryptBridgeJNI( JNIEnv* env, jobject thiz
goto END;
}

jchar *salt_chars = (*env)->GetCharArrayElements(env, salt, NULL);
jbyte *parsedSalt = (*env)->GetByteArrayElements(env, salt, NULL);
if((*env)->ExceptionOccurred(env)) {
LOGE("Failed to get salt elements.");
goto END;
}

uint8_t *parsedSalt = malloc(sizeof(uint8_t) * saltLen);
if (parsedSalt == NULL) {
msg_error = "Failed to malloc parsedSalt.";
LOGE("%s", msg_error);
throwException(env, msg_error);
goto END;
}

uint8_t *hashbuf = malloc(sizeof(uint8_t) * dkLen_i);
if (hashbuf == NULL) {
msg_error = "Failed to malloc hashbuf.";
Expand All @@ -69,10 +61,6 @@ Java_com_crypho_scrypt_RNScryptModule_scryptBridgeJNI( JNIEnv* env, jobject thiz
goto END;
}

for (i = 0; i < saltLen; ++i) {
parsedSalt[i] = (uint8_t) salt_chars[i];
}

if (libscrypt_scrypt(passphrase, passLen, parsedSalt, saltLen, N_i, r_i, p_i, hashbuf, dkLen_i)) {
switch (errno) {
case EINVAL:
Expand Down Expand Up @@ -103,9 +91,8 @@ Java_com_crypho_scrypt_RNScryptModule_scryptBridgeJNI( JNIEnv* env, jobject thiz

END:
if (passphrase) (*env)->ReleaseByteArrayElements(env, pass, passphrase, JNI_ABORT);
if (salt_chars) (*env)->ReleaseCharArrayElements(env, salt, salt_chars, JNI_ABORT);
if (parsedSalt) (*env)->ReleaseByteArrayElements(env, salt, parsedSalt, JNI_ABORT);
if (hashbuf) free(hashbuf);
if (parsedSalt) free(parsedSalt);

return result;
}
Expand Down
Binary file modified android/src/main/libs/arm64-v8a/libscrypt_jni.so
Binary file not shown.
Binary file modified android/src/main/libs/armeabi-v7a/libscrypt_jni.so
Binary file not shown.
Binary file modified android/src/main/libs/x86/libscrypt_jni.so
Binary file not shown.
Binary file modified android/src/main/libs/x86_64/libscrypt_jni.so
Binary file not shown.
1 change: 1 addition & 0 deletions example/.prettierrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ module.exports = {
singleQuote: true,
trailingComma: 'all',
semi: false,
printWidth: 120
}
Loading