├── .gitignore ├── CHANGELOG ├── LICENSE ├── README.md ├── jni ├── Android.mk ├── Application.mk ├── README.txt └── scrypt-jni.c ├── libs ├── arm64-v8a │ └── libscrypt_crypho.so ├── armeabi-v7a │ └── libscrypt_crypho.so ├── armeabi │ └── libscrypt_crypho.so ├── mips │ └── libscrypt_crypho.so ├── mips64 │ └── libscrypt_crypho.so ├── x86 │ └── libscrypt_crypho.so └── x86_64 │ └── libscrypt_crypho.so ├── package.json ├── plugin.xml ├── src ├── android │ └── com │ │ └── crypho │ │ └── plugins │ │ └── ScryptPlugin.java ├── ios │ ├── ScryptPlugin.h │ └── ScryptPlugin.m └── libscrypt │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── android.h │ ├── b64.c │ ├── b64.h │ ├── crypto-mcf.c │ ├── crypto-scrypt-saltgen.c │ ├── crypto_scrypt-check.c │ ├── crypto_scrypt-hash.c │ ├── crypto_scrypt-hexconvert.c │ ├── crypto_scrypt-hexconvert.h │ ├── crypto_scrypt-nosse.c │ ├── libscrypt.h │ ├── libscrypt.version │ ├── main.c │ ├── sha256.c │ ├── sha256.h │ ├── slowequals.c │ ├── slowequals.h │ └── sysendian.h ├── testing.config.xml ├── tests ├── package.json ├── plugin.xml └── tests.js └── www └── scrypt.js /.gitignore: -------------------------------------------------------------------------------- 1 | obj/ 2 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | 2.1.2 - 2017-06-23 5 | ------------------ 6 | 7 | - Fix unicode strings on android. 8 | [ggozad] 9 | 10 | 2.1.1 - 2017-05-19 11 | ------------------ 12 | 13 | - Fix scrypt for certain android phones. 14 | [demetris-manikas, ggozad] 15 | 16 | 2.1.0 - 2015-10-28 17 | ------------------ 18 | 19 | - Rename to cordova-plugin-scrypt, publish to npm. 20 | [ggozad] 21 | 22 | - Add testing instructions. 23 | [ggozad] 24 | 25 | 2.0.2 - 2015-04-01 26 | ------------------ 27 | 28 | - Android bug fixes. 29 | [demetris-manikas] 30 | 31 | 32 | 2.0.1 - 2015-03-24 33 | ------------------ 34 | 35 | - Android implementation. 36 | [demetris-manikas, ggozad] 37 | 38 | 1.0.2 - 2015-03-20 39 | ------------------ 40 | 41 | - Fix salt, now runs on iphone < 5s properly. 42 | [ggozad] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2015 Crypho AS 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scrypt plugin for iOS & Android 2 | 3 | ## Project no longer mantained. 4 | As Crypho does not use Cordova for a long time now, it has become clear that we cannot keep maintaining this project any longer, or give it the attention it deserves. A big thanks to all the contributors. 5 | 6 | ## Introduction 7 | 8 | [scrypt](http://www.tarsnap.com/scrypt.html) is a password-based key derivation function designed to make it costly to perform hardware attacks on the derived keys. While there exist scrypt implentations for the browser in javascript they are extremely slow and impractical for use in mobile apps. 9 | 10 | This plugin is for use with [Cordova](http://incubator.apache.org/cordova/) and allows your application to use scrypt on iOS/Android devices using native C code. It is based on [libscrypt](https://github.com/technion/libscrypt). 11 | 12 | ### Contents 13 | 14 | - [Installation](#installation) 15 | - [Plugin API](#plugin-api) 16 | - [LICENSE](#license) 17 | 18 | ##Installation 19 | 20 | Below are the methods for installing this plugin automatically using command line tools. For additional info, take a look at the [Plugman Documentation](https://github.com/apache/cordova-plugman/blob/master/README.md) and [Cordova Plugin Specification](https://github.com/alunny/cordova-plugin-spec). 21 | 22 | ### Cordova 23 | 24 | The plugin can be installed via the Cordova command line interface: 25 | 26 | * Navigate to the root folder for your phonegap project. 27 | * Run the command: 28 | 29 | ```sh 30 | cordova plugin add cordova-plugin-scrypt 31 | ``` 32 | 33 | or if you want to be running the development version, 34 | 35 | ```sh 36 | cordova plugin add https://github.com/Crypho/cordova-plugin-scrypt.git 37 | ``` 38 | 39 | ## Plugin API 40 | 41 | Grab the plugin instance variable. 42 | 43 | ```js 44 | var scrypt; 45 | 46 | document.addEventListener("deviceready", function(){ 47 | scrypt = window.plugins.scrypt; 48 | ... 49 | }); 50 | ``` 51 | 52 | You can get the derived key in hexadecimal format by invoking ``scrypt(onSuccess, onFailure, password, salt, options)`` 53 | 54 | ```js 55 | var key; 56 | 57 | scrypt( 58 | function (res) { key = res; }, 59 | function (err) { key = null }, 60 | 'password', 'salt', {N: 16384} 61 | ) 62 | ``` 63 | 64 | The ``salt`` parameter can be a string or an array of uint8. You can provide custom ``scrypt`` parameters in the options dict. The defaults are 65 | ```js 66 | { 67 | N: 16384, 68 | r: 8, 69 | p: 1, 70 | dkLen: 32 71 | } 72 | ``` 73 | 74 | ## Testing 75 | 76 | ### Setup 77 | 78 | 1. Create a cordova app. 79 | 2. Replace ``config.xml`` with the ``testing.config.xml`` 80 | 3. Add your platforms. 81 | 4. Add the ``cordova-plugin-test-framework`` plugin: 82 | 83 | ``` 84 | cordova plugin add http://git-wip-us.apache.org/repos/asf/cordova-plugin-test-framework.git 85 | ``` 86 | 87 | 4. Finally add the scrypt plugin as well as the tests from its location 88 | 89 | ``` 90 | cordova plugin add PATH_TO_SCRYPT_PLUGIN 91 | cordova plugin add PATH_TO_SCRYPT_PLUGIN/tests 92 | ``` 93 | 94 | ### Running the tests 95 | 96 | Just run the app for all platforms. Remember, if you have changes to test you will need to remove the scrypt plugin and add it again for the changes to be seen by the app. 97 | 98 | ## LICENSE 99 | 100 | The MIT License 101 | 102 | Copyright (c) 2015 Crypho AS. 103 | 104 | Permission is hereby granted, free of charge, to any person obtaining a copy 105 | of this software and associated documentation files (the "Software"), to deal 106 | in the Software without restriction, including without limitation the rights 107 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 108 | copies of the Software, and to permit persons to whom the Software is 109 | furnished to do so, subject to the following conditions: 110 | 111 | The above copyright notice and this permission notice shall be included in 112 | all copies or substantial portions of the Software. 113 | 114 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 115 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 116 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 117 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 118 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 119 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 120 | THE SOFTWARE. 121 | 122 | libscrypt is Copyright (c) 2013, Joshua Small under the BSD license. See src/libscrypt/LICENSE 123 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | include $(CLEAR_VARS) 3 | LOCAL_MODULE := scrypt 4 | LOCAL_SCRYPT_SRC := $(LOCAL_PATH)/../src/libscrypt 5 | LOCAL_C_INCLUDES := $(LOCAL_SCRYPT_SRC)/ 6 | 7 | LOCAL_SRC_FILES := \ 8 | $(LOCAL_SCRYPT_SRC)/b64.c \ 9 | $(LOCAL_SCRYPT_SRC)/crypto_scrypt-hexconvert.c \ 10 | $(LOCAL_SCRYPT_SRC)/sha256.c \ 11 | $(LOCAL_SCRYPT_SRC)/crypto-mcf.c \ 12 | $(LOCAL_SCRYPT_SRC)/crypto_scrypt-nosse.c \ 13 | $(LOCAL_SCRYPT_SRC)/slowequals.c \ 14 | $(LOCAL_SCRYPT_SRC)/crypto_scrypt-check.c \ 15 | $(LOCAL_SCRYPT_SRC)/crypto-scrypt-saltgen.c \ 16 | $(LOCAL_SCRYPT_SRC)/crypto_scrypt-hash.c \ 17 | $(LOCAL_SCRYPT_SRC)/main.c 18 | 19 | include $(BUILD_STATIC_LIBRARY) 20 | 21 | include $(CLEAR_VARS) 22 | LOCAL_MODULE := scrypt_crypho 23 | LOCAL_STATIC_LIBRARIES := scrypt 24 | 25 | LOCAL_SCRYPT_SRC := $(LOCAL_PATH)/../src/libscrypt 26 | LOCAL_C_INCLUDES := $(LOCAL_SCRYPT_SRC) 27 | 28 | LOCAL_CRYPHO_SRC := $(LOCAL_PATH) 29 | LOCAL_SRC_FILES := $(LOCAL_PATH)/scrypt-jni.c 30 | 31 | LOCAL_LDLIBS := -llog 32 | 33 | include $(BUILD_SHARED_LIBRARY) -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-19 2 | 3 | APP_ABI := all 4 | -------------------------------------------------------------------------------- /jni/README.txt: -------------------------------------------------------------------------------- 1 | To create the shared libraries run ndk-build from inside the jni directory -------------------------------------------------------------------------------- /jni/scrypt-jni.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "libscrypt.h" 8 | 9 | #define LOG_TAG "libscrypt_crypho" 10 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 11 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 12 | #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__) 13 | 14 | static jobject JC_Integer; 15 | static jmethodID JMID_Integer_intValue; 16 | 17 | static jint callIntMethod(JNIEnv* env, jmethodID method, jobject integerObject, jint defaultValue); 18 | static void throwException(JNIEnv* env, char *msg); 19 | 20 | JNIEXPORT jbyteArray JNICALL 21 | Java_com_crypho_plugins_ScryptPlugin_scrypt( JNIEnv* env, jobject thiz, 22 | jbyteArray pass, jcharArray salt, jobject N, jobject r, jobject p, jobject dkLen) 23 | { 24 | int i; 25 | char *msg_error; 26 | 27 | jint N_i = callIntMethod(env, JMID_Integer_intValue, N, SCRYPT_N); 28 | jint r_i = callIntMethod(env, JMID_Integer_intValue, r, SCRYPT_r); 29 | jint p_i = callIntMethod(env, JMID_Integer_intValue, p, SCRYPT_p); 30 | jint dkLen_i = callIntMethod(env, JMID_Integer_intValue, dkLen, 32); 31 | 32 | jint passLen = (*env)->GetArrayLength(env, pass); 33 | if((*env)->ExceptionOccurred(env)) { 34 | LOGE("Failed to get passphrase lenght."); 35 | goto END; 36 | } 37 | 38 | jint saltLen = (*env)->GetArrayLength(env, salt); 39 | if((*env)->ExceptionOccurred(env)) { 40 | LOGE("Failed to get salt lenght."); 41 | goto END; 42 | } 43 | 44 | jbyte *passphrase = (*env)->GetByteArrayElements(env, pass, NULL); 45 | if((*env)->ExceptionOccurred(env)) { 46 | LOGE("Failed to get passphrase elements."); 47 | goto END; 48 | } 49 | 50 | jchar *salt_chars = (*env)->GetCharArrayElements(env, salt, NULL); 51 | if((*env)->ExceptionOccurred(env)) { 52 | LOGE("Failed to get salt elements."); 53 | goto END; 54 | } 55 | 56 | uint8_t *parsedSalt = malloc(sizeof(uint8_t) * saltLen); 57 | if (parsedSalt == NULL) { 58 | msg_error = "Failed to malloc parsedSalt."; 59 | LOGE("%s", msg_error); 60 | throwException(env, msg_error); 61 | goto END; 62 | } 63 | 64 | uint8_t *hashbuf = malloc(sizeof(uint8_t) * dkLen_i); 65 | if (hashbuf == NULL) { 66 | msg_error = "Failed to malloc hashbuf."; 67 | LOGE("%s", msg_error); 68 | throwException(env, msg_error); 69 | goto END; 70 | } 71 | 72 | for (i = 0; i < saltLen; ++i) { 73 | parsedSalt[i] = (uint8_t) salt_chars[i]; 74 | } 75 | 76 | if (libscrypt_scrypt(passphrase, passLen, parsedSalt, saltLen, N_i, r_i, p_i, hashbuf, dkLen_i)) { 77 | switch (errno) { 78 | case EINVAL: 79 | msg_error = "N must be a power of 2 greater than 1."; 80 | break; 81 | case EFBIG: 82 | case ENOMEM: 83 | msg_error = "Insufficient memory available."; 84 | break; 85 | default: 86 | msg_error = "Memory allocation failed."; 87 | } 88 | throwException(env, msg_error); 89 | goto END; 90 | } 91 | 92 | jbyteArray result = (*env)->NewByteArray(env, dkLen_i); 93 | if((*env)->ExceptionOccurred(env)) { 94 | LOGE("Failed to allocate result buffer."); 95 | goto END; 96 | } 97 | 98 | (*env)->SetByteArrayRegion(env, result, 0, dkLen_i, (jbyte *) hashbuf); 99 | if((*env)->ExceptionOccurred(env)) { 100 | LOGE("Failed to set result buffer."); 101 | goto END; 102 | } 103 | 104 | END: 105 | if (passphrase) (*env)->ReleaseByteArrayElements(env, pass, passphrase, JNI_ABORT); 106 | if (salt_chars) (*env)->ReleaseCharArrayElements(env, salt, salt_chars, JNI_ABORT); 107 | if (hashbuf) free(hashbuf); 108 | if (parsedSalt) free(parsedSalt); 109 | 110 | return result; 111 | } 112 | 113 | static jint 114 | callIntMethod(JNIEnv* env, jmethodID method, jobject integerObject, jint defaultValue) { 115 | if (integerObject == NULL) { 116 | return defaultValue; 117 | } 118 | jint result = (*env)->CallIntMethod(env, integerObject, method); 119 | if((*env)->ExceptionOccurred(env)) { 120 | return defaultValue; 121 | } 122 | return result; 123 | } 124 | 125 | static void 126 | throwException(JNIEnv* env, char *msg) { 127 | jclass JC_Exception = (*env)->FindClass(env, "java/lang/Exception"); 128 | (*env)->ThrowNew(env, JC_Exception, msg); 129 | } 130 | 131 | JNIEXPORT jint JNICALL 132 | JNI_OnLoad(JavaVM* vm, void* aReserved){ 133 | JNIEnv* env; 134 | jclass aClass; 135 | 136 | if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK){ 137 | LOGE("Failed to get the environment"); 138 | return JNI_ERR; 139 | } 140 | 141 | aClass = (*env)->FindClass(env, "java/lang/Integer"); 142 | if((*env)->ExceptionOccurred(env)) { 143 | LOGE("Failed to load class java.lang.Integer."); 144 | return JNI_ERR; 145 | } 146 | 147 | JC_Integer = (*env)->NewWeakGlobalRef(env, aClass); 148 | if((*env)->ExceptionOccurred(env)) { 149 | LOGE("Failed to asign global java.lang.Integer."); 150 | return JNI_ERR; 151 | } 152 | 153 | (*env)->DeleteLocalRef(env, aClass); 154 | if((*env)->ExceptionOccurred(env)) { 155 | LOGE("Failed to delete local ref of java.lang.Integer."); 156 | return JNI_ERR; 157 | } 158 | 159 | JMID_Integer_intValue = (*env)->GetMethodID(env, JC_Integer, "intValue", "()I"); 160 | if((*env)->ExceptionOccurred(env)) { 161 | LOGE("Failed to fetch inValue method from java.lang.Integer."); 162 | return JNI_ERR; 163 | } 164 | 165 | // env->RegisterNatives(activityClass, methodTable, sizeof(methodTable) / sizeof(methodTable[0])); 166 | return JNI_VERSION_1_6; 167 | } 168 | 169 | JNIEXPORT void JNICALL 170 | JNI_OnUnLoad(JavaVM* vm, void* aReserved){ 171 | JNIEnv* env; 172 | 173 | if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK){ 174 | LOGE("Failed to get the environment"); 175 | return; 176 | } 177 | (*env)->DeleteWeakGlobalRef(env, JC_Integer); 178 | } -------------------------------------------------------------------------------- /libs/arm64-v8a/libscrypt_crypho.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crypho/cordova-plugin-scrypt/a6d6f3fffab4cf49598795303e30448892ee1c59/libs/arm64-v8a/libscrypt_crypho.so -------------------------------------------------------------------------------- /libs/armeabi-v7a/libscrypt_crypho.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crypho/cordova-plugin-scrypt/a6d6f3fffab4cf49598795303e30448892ee1c59/libs/armeabi-v7a/libscrypt_crypho.so -------------------------------------------------------------------------------- /libs/armeabi/libscrypt_crypho.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crypho/cordova-plugin-scrypt/a6d6f3fffab4cf49598795303e30448892ee1c59/libs/armeabi/libscrypt_crypho.so -------------------------------------------------------------------------------- /libs/mips/libscrypt_crypho.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crypho/cordova-plugin-scrypt/a6d6f3fffab4cf49598795303e30448892ee1c59/libs/mips/libscrypt_crypho.so -------------------------------------------------------------------------------- /libs/mips64/libscrypt_crypho.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crypho/cordova-plugin-scrypt/a6d6f3fffab4cf49598795303e30448892ee1c59/libs/mips64/libscrypt_crypho.so -------------------------------------------------------------------------------- /libs/x86/libscrypt_crypho.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crypho/cordova-plugin-scrypt/a6d6f3fffab4cf49598795303e30448892ee1c59/libs/x86/libscrypt_crypho.so -------------------------------------------------------------------------------- /libs/x86_64/libscrypt_crypho.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crypho/cordova-plugin-scrypt/a6d6f3fffab4cf49598795303e30448892ee1c59/libs/x86_64/libscrypt_crypho.so -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-scrypt", 3 | "version": "2.1.2", 4 | "description": "An scrypt implementation for cordova apps in iOS and Android.", 5 | "author": "Yiorgis Gozadinos ", 6 | "contributors": [ 7 | {"name": "Demetris Manikas", "email": "demetris.manikas@gmail.com"} 8 | ], 9 | "cordova": { 10 | "id": "cordova-plugin-scrypt", 11 | "platforms": [ 12 | "android", 13 | "ios" 14 | ] 15 | }, 16 | "keywords": [ 17 | "cordova", 18 | "security", 19 | "encryption", 20 | "scrypt", 21 | "ecosystem:cordova", 22 | "cordova-android", 23 | "cordova-ios", 24 | "cordova-browser" 25 | ], 26 | "main": "www/securestorage.js", 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/crypho/cordova-plugin-scrypt.git" 30 | }, 31 | "devDependencies": { 32 | "cordova-plugin-test-framework": ">=1.0.0" 33 | }, 34 | "license": "MIT", 35 | "bugs": { 36 | "url": "https://github.com/crypho/cordova-plugin-scrypt/issues" 37 | }, 38 | "homepage": "https://github.com/crypho/cordova-plugin-scrypt#readme" 39 | } 40 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | ScryptPlugin 8 | Crypho AS 9 | 10 | 11 | An scrypt implementation for cordova apps in iOS and Android. 12 | 13 | 14 | MIT 15 | 16 | scrypt, encryption 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/android/com/crypho/plugins/ScryptPlugin.java: -------------------------------------------------------------------------------- 1 | package com.crypho.plugins; 2 | 3 | import android.util.Log; 4 | 5 | import org.apache.cordova.CallbackContext; 6 | import org.apache.cordova.CordovaArgs; 7 | import org.apache.cordova.CordovaInterface; 8 | import org.apache.cordova.CordovaPlugin; 9 | import org.apache.cordova.CordovaWebView; 10 | import org.apache.cordova.PluginResult; 11 | import org.json.JSONArray; 12 | import org.json.JSONObject; 13 | import org.json.JSONException; 14 | 15 | public class ScryptPlugin extends CordovaPlugin { 16 | private static final String TAG = "Scrypt"; 17 | private static final char[] HEX = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 18 | 19 | static { 20 | System.loadLibrary("scrypt_crypho"); 21 | } 22 | 23 | public native byte[] scrypt(byte[] pass, char[] salt, Integer N, Integer r, Integer p, Integer dkLen); 24 | 25 | @Override 26 | public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException { 27 | if ("scrypt".equals(action)) { 28 | String parsedSalt = null; 29 | final String arg_passphrase = args.getString(0); 30 | final char[] arg_salt = getSalt(args.get(1)); 31 | 32 | JSONObject options = args.getJSONObject(2); 33 | final Integer N = getIntegerOption("N", options); 34 | final Integer r = getIntegerOption("r", options); 35 | final Integer p = getIntegerOption("p", options); 36 | final Integer dkLen = getIntegerOption("dkLen", options); 37 | 38 | cordova.getThreadPool().execute(new Runnable() { 39 | public void run() { 40 | try { 41 | byte[] passwordBytes = arg_passphrase.getBytes("UTF-8"); 42 | byte[] res = scrypt(passwordBytes, arg_salt, N, r, p, dkLen); 43 | String result = hexify(res); 44 | callbackContext.success(result); 45 | } catch (Exception e) { 46 | Log.e(TAG, "Scrypt Failed: " + e.getMessage()); 47 | callbackContext.error(e.getMessage()); 48 | } 49 | } 50 | }); 51 | return true; 52 | } 53 | return false; 54 | } 55 | 56 | private String hexify (byte[] input) { 57 | int len = input.length; 58 | char[] result = new char[2 * len]; 59 | for ( int j = 0; j < len; j++ ) { 60 | int v = input[j] & 0xFF; 61 | result[j * 2] = HEX[v >>> 4]; 62 | result[j * 2 + 1] = HEX[v & 0x0F]; 63 | } 64 | return new String(result).toLowerCase(); 65 | } 66 | 67 | private Integer getIntegerOption(String option, JSONObject options) { 68 | int arg = options.optInt(option); 69 | return arg != 0 ? Integer.valueOf(arg) : null; 70 | } 71 | 72 | private char[] getSalt(Object src){ 73 | if (src instanceof JSONArray) { 74 | JSONArray tmp = (JSONArray) src; 75 | int len = tmp.length(); 76 | char[] result = new char[len]; 77 | for (int i = 0; i < len ; i++) { 78 | result[i] = (char) tmp.optInt(i); 79 | } 80 | return result; 81 | } else { 82 | return ((String) src).toCharArray(); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/ios/ScryptPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ScryptPlugin : CDVPlugin 4 | 5 | - (void)scrypt:(CDVInvokedUrlCommand*)command; 6 | 7 | @property (nonatomic, copy) NSString *callbackId; 8 | 9 | @end 10 | 11 | -------------------------------------------------------------------------------- /src/ios/ScryptPlugin.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "ScryptPlugin.h" 3 | #import "libscrypt.h" 4 | #import 5 | 6 | @implementation ScryptPlugin 7 | 8 | @synthesize callbackId; 9 | 10 | - (void)scrypt:(CDVInvokedUrlCommand*)command 11 | { 12 | 13 | int i, success; 14 | size_t saltLength; 15 | const uint8_t *parsedSalt; 16 | uint8_t *buffer = NULL; 17 | const char* passphrase = [[command argumentAtIndex:0] UTF8String]; 18 | id salt = [command argumentAtIndex:1]; 19 | 20 | if ([salt isKindOfClass:[NSString class]]) { 21 | parsedSalt = (const uint8_t *)[salt UTF8String]; 22 | saltLength = (size_t) [salt length]; 23 | } else if ([salt isKindOfClass:[NSArray class]]) { 24 | saltLength = (int) [salt count]; 25 | buffer = malloc(sizeof(uint8_t) * saltLength); 26 | 27 | for (i = 0; i < saltLength; ++i) { 28 | buffer[i] = (uint8_t)[[salt objectAtIndex:i] integerValue]; 29 | } 30 | parsedSalt = buffer; 31 | } 32 | 33 | // Parse options 34 | NSMutableDictionary* options = [command.arguments objectAtIndex:2]; 35 | uint64_t N = [options[@"N"] unsignedLongValue] ?: SCRYPT_N; 36 | uint32_t r = [options[@"r"] unsignedShortValue] ?: SCRYPT_r; 37 | uint32_t p = [options[@"p"] unsignedShortValue] ?: SCRYPT_p; 38 | uint32_t dkLen = [options[@"dkLen"] unsignedShortValue] ?: 32; 39 | 40 | uint8_t hashbuf[dkLen]; 41 | self.callbackId = command.callbackId; 42 | 43 | @try { 44 | success = libscrypt_scrypt((uint8_t *)passphrase, strlen(passphrase), parsedSalt, saltLength, N, r, p, hashbuf, dkLen); 45 | } 46 | @catch (NSException * e) { 47 | [self failWithMessage: [NSString stringWithFormat:@"%@", e] withError: nil]; 48 | } 49 | 50 | if (success!=0) { 51 | [self failWithMessage: @"Failure in scrypt" withError: nil]; 52 | } 53 | 54 | 55 | // Hexify 56 | NSMutableString *hexResult = [NSMutableString stringWithCapacity:dkLen * 2]; 57 | for(i = 0;i < dkLen; i++ ) 58 | { 59 | [hexResult appendFormat:@"%02x", hashbuf[i]]; 60 | } 61 | NSString *result = [NSString stringWithString: hexResult]; 62 | [self successWithMessage: result]; 63 | 64 | free(buffer); 65 | } 66 | 67 | -(void)successWithMessage:(NSString *)message 68 | { 69 | if (self.callbackId != nil) 70 | { 71 | CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message]; 72 | [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId]; 73 | } 74 | } 75 | 76 | -(void)failWithMessage:(NSString *)message withError:(NSError *)error 77 | { 78 | NSString *errorMessage = (error) ? [NSString stringWithFormat:@"%@ - %@", message, [error localizedDescription]] : message; 79 | CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage]; 80 | 81 | [self.commandDelegate sendPluginResult:commandResult callbackId:self.callbackId]; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /src/libscrypt/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Joshua Small 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | 10 | -------------------------------------------------------------------------------- /src/libscrypt/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | LIBDIR ?= $(PREFIX)/lib 3 | INCLUDEDIR ?= $(PREFIX)/include 4 | MAKE_DIR ?= install -d 5 | INSTALL_DATA ?= install 6 | 7 | CC?=gcc 8 | CFLAGS?=-O2 -Wall -g -D_FORTIFY_SOURCE=2 -fstack-protector -fPIC 9 | LDFLAGS?=-Wl,-z,now -Wl,-z,relro -Wl,-soname,libscrypt.so.0 -Wl,--version-script=libscrypt.version 10 | CFLAGS_EXTRA?=-Wl,-rpath=. 11 | 12 | all: reference 13 | 14 | OBJS= crypto_scrypt-nosse.o sha256.o crypto-mcf.o b64.o crypto-scrypt-saltgen.o crypto_scrypt-check.o crypto_scrypt-hash.o slowequals.o 15 | 16 | libscrypt.so.0: $(OBJS) 17 | $(CC) $(LDFLAGS) -shared -o libscrypt.so.0 $(OBJS) -lm -lc 18 | ar rcs libscrypt.a $(OBJS) 19 | 20 | reference: libscrypt.so.0 main.o crypto_scrypt-hexconvert.o 21 | ln -s -f libscrypt.so.0 libscrypt.so 22 | $(CC) -Wall -o reference main.o b64.o crypto_scrypt-hexconvert.o $(CFLAGS_EXTRA) -L. -lscrypt 23 | 24 | clean: 25 | rm -f *.o reference libscrypt.so* libscrypt.a endian.h 26 | 27 | check: all 28 | ./reference 29 | 30 | devtest: 31 | splint crypto_scrypt-hexconvert.c 32 | splint crypto-mcf.c crypto_scrypt-check.c crypto_scrypt-hash.c -unrecog 33 | splint crypto-scrypt-saltgen.c +posixlib -compdef 34 | valgrind ./reference 35 | 36 | asan: main.c 37 | clang -O1 -g -fsanitize=address -fno-omit-frame-pointer *.c -o asantest 38 | ./asantest 39 | scan-build clang -O1 -g -fsanitize=memory -fno-omit-frame-pointer *.c -o asantest 40 | ./asantest 41 | rm -f asantest 42 | 43 | install: libscrypt.so.0 44 | $(MAKE_DIR) $(DESTDIR) $(DESTDIR)$(PREFIX) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR) 45 | $(INSTALL_DATA) -pm 0755 libscrypt.so.0 $(DESTDIR)$(LIBDIR) 46 | cd $(DESTDIR)$(LIBDIR) && ln -s -f libscrypt.so.0 $(DESTDIR)$(LIBDIR)/libscrypt.so 47 | $(INSTALL_DATA) -pm 0644 libscrypt.h $(DESTDIR)$(INCLUDEDIR) 48 | 49 | install-osx: libscrypt.so.0 50 | $(MAKE_DIR) $(DESTDIR) $(DESTDIR)$(PREFIX) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR) 51 | $(INSTALL_DATA) -pm 0755 libscrypt.so.0 $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib 52 | cd $(DESTDIR)$(LIBDIR) && install_name_tool -id $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib $(DESTDIR)$(LIBDIR)/libscrypt.0.dylib 53 | cd $(DESTDIR)$(LIBDIR) && ln -s -f libscrypt.0.dylib $(DESTDIR)$(LIBDIR)/libscrypt.dylib 54 | $(INSTALL_DATA) -pm 0644 libscrypt.h $(DESTDIR)$(INCLUDEDIR) 55 | 56 | install-static: libscrypt.a 57 | $(INSTALL_DATA) -pm 0644 libscrypt.a $(DESTDIR)$(LIBDIR) 58 | -------------------------------------------------------------------------------- /src/libscrypt/README.md: -------------------------------------------------------------------------------- 1 | libscrypt 2 | ========= 3 | Linux scrypt shared library. 4 | 5 | Full credit to algorithm designer and example code from Colin Percival here: 6 | http://www.tarsnap.com/scrypt.html 7 | 8 | Utilises BASE64 encoding library from ISC. 9 | 10 | Official project page, including stable tarballs found here: 11 | http://www.lolware.net/libscrypt.html 12 | 13 | Simple hashing interface 14 | 15 | The (reference) internal hashing function can be directly called as follows: 16 | 17 | int libscrypt_scrypt(const uint8_t *passwd, size_t passwdlen, 18 | const uint8_t *salt, size_t saltlen, uint64_t N, uint32_t r, 19 | uint32_t p, /*@out@*/ uint8_t *buf, size_t buflen); 20 | 21 | Libscrypt's easier to use interface wraps this up to deal with the salt and produce BASE64 output as so: 22 | 23 | int libscrypt_hash(char *dst, char *passphrase, uint32_t N, uint8_t r, uint8_t p); 24 | 25 | Sane constants have been created for N, r and p so you can create a hash like this: 26 | 27 | libscrypt_hash(outbuf, "My cats's breath smells like cat food", SCRYPT_N, SCRYPT_r, SCRYPT_p); 28 | 29 | This function sets errno as required for any error conditions. 30 | 31 | Output stored in "outbuf" is stored in a standardised MCF form, which means includes the randomly created, 128 bit salt, all N, r and p values, and a BASE64 encoded version of the hash. The entire MCF can be stored in a database, and compared for use as below: 32 | 33 | retval = libscrypt_check(mcf, "pleasefailme"); 34 | retval < 0 error 35 | retval = 0 password incorrect 36 | retval > 0 pass 37 | 38 | mcf should be defined as at least SCRYPT_MCF_LEN in size. 39 | 40 | Note that libscrypt_check needs to modify the mcf string and will not return it 41 | to the original state. Pass it a copy if you need to keep the original mcf. 42 | 43 | A number of internal functions are exposed, and users wishing to create more complex use cases should consult the header file, which is aimed at documenting the API fully. 44 | 45 | The test reference is also aimed at providing a well documented use case. 46 | Building 47 | -------- 48 | make 49 | make check 50 | Check the Makefile for advice on linking against your application. 51 | 52 | OSX 53 | ----- 54 | Please compile and install with: 55 | 56 | make LDFLAGS= CFLAGS_EXTRA= 57 | make install-osx 58 | 59 | 60 | BUGS 61 | ---- 62 | SCRYPT_* constants are probably a little high for something like a Raspberry pi. Using '1' as SCRYPT_p is acceptable from a security and performance standpoint if needed. 63 | Experiments were performed with using memset() to zero out passwords as they were checked. This often caused issues with calling applications where the password based have been passed as a const*. We highly recommend implementing your own zeroing function the moment this library is called. 64 | 65 | Notes on Code Development 66 | ------------------------ 67 | 68 | Code is now declared "stable", the master branch will always be "stable" and development will be done on branches. 69 | The reference machines are Fedora, CentOS, FreeBSD and Raspbian, and the code is expected to compile and run on all of these before being moved to stable branch. 70 | Full transparancy on the regular application of thorough testing can be found by reviewing recent test harness results here: 71 | http://www.lolware.net/libscrypttesting.txt 72 | 73 | Please, no more pull requests for Windows compatibility. If it's important to you - fork the project. I have no intention of pulling an OpenSSL and becoming a maze of ifdefs for platforms I don't even have a build environment for. 74 | 75 | Contact 76 | ------- 77 | I can be contacted at: technion@lolware.net 78 | 79 | If required, my GPG key can be found at: https://lolware.net/technion-GPG-KEY 80 | 81 | Future releases will have the Git tag signed. 82 | 83 | 84 | Changenotes 85 | ----------- 86 | v1.1a: Single Makefile line change. I wouldn't ordinarily tag this as a new "release", but the purpose here is to assist with packaging in distributions. 87 | 88 | v1.12: The static library is built, but no longer installed by default. You can install it with "make install-static". This is because static libraries are not typically bundled in packages. 89 | 90 | v1.13: Minor packaging related update 91 | 92 | v1.15: Replaced the b64 libraries with more portable one from ISC. Now tested and verified on a wider variety of architectures. Note, libscrypt_b64_encrypt was originally an exported function. This is no longer the case as it is considered an internal function only. 93 | 94 | v1.18: God damnit Apple 95 | 96 | v1.19: Code safety cleanups. Now running Coverity. 97 | 98 | v1.20: Bigfixes involving large N values, return values on error 99 | 100 | 101 | Coverity Scan Build Status 103 | 104 | -------------------------------------------------------------------------------- /src/libscrypt/android.h: -------------------------------------------------------------------------------- 1 | #ifndef SIZE_MAX 2 | # if defined(__LP64__) 3 | # define SIZE_MAX UINT64_MAX 4 | # else 5 | # define SIZE_MAX UINT32_MAX 6 | # endif 7 | #endif -------------------------------------------------------------------------------- /src/libscrypt/b64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1996 by Internet Software Consortium. 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 9 | * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 10 | * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 11 | * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 13 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 14 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 15 | * SOFTWARE. 16 | */ 17 | 18 | /* 19 | * Portions Copyright (c) 1995 by International Business Machines, Inc. 20 | * 21 | * International Business Machines, Inc. (hereinafter called IBM) grants 22 | * permission under its copyrights to use, copy, modify, and distribute this 23 | * Software with or without fee, provided that the above copyright notice and 24 | * all paragraphs of this notice appear in all copies, and that the name of IBM 25 | * not be used in connection with the marketing of any product incorporating 26 | * the Software or modifications thereof, without specific, written prior 27 | * permission. 28 | * 29 | * To the extent it has a right to do so, IBM grants an immunity from suit 30 | * under its patents, if any, for the use, sale or manufacture of products to 31 | * the extent that such products are used for performing Domain Name System 32 | * dynamic updates in TCP/IP networks by means of the Software. No immunity is 33 | * granted for any product per se or for any other function of any product. 34 | * 35 | * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 36 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 37 | * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 38 | * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 39 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 40 | * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 41 | */ 42 | 43 | /* 44 | * Base64 encode/decode functions from OpenBSD (src/lib/libc/net/base64.c). 45 | */ 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | #include "b64.h" 53 | 54 | 55 | static const char Base64[] = 56 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 57 | static const char Pad64 = '='; 58 | 59 | /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) 60 | The following encoding technique is taken from RFC 1521 by Borenstein 61 | and Freed. It is reproduced here in a slightly edited form for 62 | convenience. 63 | 64 | A 65-character subset of US-ASCII is used, enabling 6 bits to be 65 | represented per printable character. (The extra 65th character, "=", 66 | is used to signify a special processing function.) 67 | 68 | The encoding process represents 24-bit groups of input bits as output 69 | strings of 4 encoded characters. Proceeding from left to right, a 70 | 24-bit input group is formed by concatenating 3 8-bit input groups. 71 | These 24 bits are then treated as 4 concatenated 6-bit groups, each 72 | of which is translated into a single digit in the base64 alphabet. 73 | 74 | Each 6-bit group is used as an index into an array of 64 printable 75 | characters. The character referenced by the index is placed in the 76 | output string. 77 | 78 | Table 1: The Base64 Alphabet 79 | 80 | Value Encoding Value Encoding Value Encoding Value Encoding 81 | 0 A 17 R 34 i 51 z 82 | 1 B 18 S 35 j 52 0 83 | 2 C 19 T 36 k 53 1 84 | 3 D 20 U 37 l 54 2 85 | 4 E 21 V 38 m 55 3 86 | 5 F 22 W 39 n 56 4 87 | 6 G 23 X 40 o 57 5 88 | 7 H 24 Y 41 p 58 6 89 | 8 I 25 Z 42 q 59 7 90 | 9 J 26 a 43 r 60 8 91 | 10 K 27 b 44 s 61 9 92 | 11 L 28 c 45 t 62 + 93 | 12 M 29 d 46 u 63 / 94 | 13 N 30 e 47 v 95 | 14 O 31 f 48 w (pad) = 96 | 15 P 32 g 49 x 97 | 16 Q 33 h 50 y 98 | 99 | Special processing is performed if fewer than 24 bits are available 100 | at the end of the data being encoded. A full encoding quantum is 101 | always completed at the end of a quantity. When fewer than 24 input 102 | bits are available in an input group, zero bits are added (on the 103 | right) to form an integral number of 6-bit groups. Padding at the 104 | end of the data is performed using the '=' character. 105 | 106 | Since all base64 input is an integral number of octets, only the 107 | ------------------------------------------------- 108 | following cases can arise: 109 | 110 | (1) the final quantum of encoding input is an integral 111 | multiple of 24 bits; here, the final unit of encoded 112 | output will be an integral multiple of 4 characters 113 | with no "=" padding, 114 | (2) the final quantum of encoding input is exactly 8 bits; 115 | here, the final unit of encoded output will be two 116 | characters followed by two "=" padding characters, or 117 | (3) the final quantum of encoding input is exactly 16 bits; 118 | here, the final unit of encoded output will be three 119 | characters followed by one "=" padding character. 120 | */ 121 | 122 | int 123 | libscrypt_b64_encode(src, srclength, target, targsize) 124 | unsigned char const *src; 125 | size_t srclength; 126 | char *target; 127 | size_t targsize; 128 | { 129 | size_t datalength = 0; 130 | unsigned char input[3]; 131 | unsigned char output[4]; 132 | unsigned int i; 133 | 134 | while (2 < srclength) { 135 | input[0] = *src++; 136 | input[1] = *src++; 137 | input[2] = *src++; 138 | srclength -= 3; 139 | 140 | output[0] = input[0] >> 2; 141 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 142 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 143 | output[3] = input[2] & 0x3f; 144 | 145 | if (datalength + 4 > targsize) 146 | return (-1); 147 | target[datalength++] = Base64[output[0]]; 148 | target[datalength++] = Base64[output[1]]; 149 | target[datalength++] = Base64[output[2]]; 150 | target[datalength++] = Base64[output[3]]; 151 | } 152 | 153 | /* Now we worry about padding. */ 154 | if (0 != srclength) { 155 | /* Get what's left. */ 156 | input[0] = input[1] = input[2] = '\0'; 157 | for (i = 0; i < srclength; i++) 158 | input[i] = *src++; 159 | 160 | output[0] = input[0] >> 2; 161 | output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); 162 | output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); 163 | 164 | if (datalength + 4 > targsize) 165 | return (-1); 166 | target[datalength++] = Base64[output[0]]; 167 | target[datalength++] = Base64[output[1]]; 168 | if (srclength == 1) 169 | target[datalength++] = Pad64; 170 | else 171 | target[datalength++] = Base64[output[2]]; 172 | target[datalength++] = Pad64; 173 | } 174 | if (datalength >= targsize) 175 | return (-1); 176 | target[datalength] = '\0'; /* Returned value doesn't count \0. */ 177 | return (int)(datalength); 178 | } 179 | 180 | /* skips all whitespace anywhere. 181 | converts characters, four at a time, starting at (or after) 182 | src from base - 64 numbers into three 8 bit bytes in the target area. 183 | it returns the number of data bytes stored at the target, or -1 on error. 184 | */ 185 | 186 | int 187 | libscrypt_b64_decode(src, target, targsize) 188 | char const *src; 189 | unsigned char *target; 190 | size_t targsize; 191 | { 192 | int state, ch; 193 | unsigned int tarindex; 194 | unsigned char nextbyte; 195 | char *pos; 196 | 197 | state = 0; 198 | tarindex = 0; 199 | 200 | while ((ch = (unsigned char)*src++) != '\0') { 201 | if (isspace(ch)) /* Skip whitespace anywhere. */ 202 | continue; 203 | 204 | if (ch == Pad64) 205 | break; 206 | 207 | pos = strchr(Base64, ch); 208 | if (pos == 0) /* A non-base64 character. */ 209 | return (-1); 210 | 211 | switch (state) { 212 | case 0: 213 | if (target) { 214 | if (tarindex >= targsize) 215 | return (-1); 216 | target[tarindex] = (pos - Base64) << 2; 217 | } 218 | state = 1; 219 | break; 220 | case 1: 221 | if (target) { 222 | if (tarindex >= targsize) 223 | return (-1); 224 | target[tarindex] |= (pos - Base64) >> 4; 225 | nextbyte = ((pos - Base64) & 0x0f) << 4; 226 | if (tarindex + 1 < targsize) 227 | target[tarindex+1] = nextbyte; 228 | else if (nextbyte) 229 | return (-1); 230 | } 231 | tarindex++; 232 | state = 2; 233 | break; 234 | case 2: 235 | if (target) { 236 | if (tarindex >= targsize) 237 | return (-1); 238 | target[tarindex] |= (pos - Base64) >> 2; 239 | nextbyte = ((pos - Base64) & 0x03) << 6; 240 | if (tarindex + 1 < targsize) 241 | target[tarindex+1] = nextbyte; 242 | else if (nextbyte) 243 | return (-1); 244 | } 245 | tarindex++; 246 | state = 3; 247 | break; 248 | case 3: 249 | if (target) { 250 | if (tarindex >= targsize) 251 | return (-1); 252 | target[tarindex] |= (pos - Base64); 253 | } 254 | tarindex++; 255 | state = 0; 256 | break; 257 | } 258 | } 259 | 260 | /* 261 | * We are done decoding Base-64 chars. Let's see if we ended 262 | * on a byte boundary, and/or with erroneous trailing characters. 263 | */ 264 | 265 | if (ch == Pad64) { /* We got a pad char. */ 266 | ch = (unsigned char)*src++; /* Skip it, get next. */ 267 | switch (state) { 268 | case 0: /* Invalid = in first position */ 269 | case 1: /* Invalid = in second position */ 270 | return (-1); 271 | 272 | case 2: /* Valid, means one byte of info */ 273 | /* Skip any number of spaces. */ 274 | for (; ch != '\0'; ch = (unsigned char)*src++) 275 | if (!isspace(ch)) 276 | break; 277 | /* Make sure there is another trailing = sign. */ 278 | if (ch != Pad64) 279 | return (-1); 280 | ch = (unsigned char)*src++; /* Skip the = */ 281 | /* Fall through to "single trailing =" case. */ 282 | /* FALLTHROUGH */ 283 | 284 | case 3: /* Valid, means two bytes of info */ 285 | /* 286 | * We know this char is an =. Is there anything but 287 | * whitespace after it? 288 | */ 289 | for (; ch != '\0'; ch = (unsigned char)*src++) 290 | if (!isspace(ch)) 291 | return (-1); 292 | 293 | /* 294 | * Now make sure for cases 2 and 3 that the "extra" 295 | * bits that slopped past the last full byte were 296 | * zeros. If we don't check them, they become a 297 | * subliminal channel. 298 | */ 299 | if (target && tarindex < targsize && 300 | target[tarindex] != 0) 301 | return (-1); 302 | } 303 | } else { 304 | /* 305 | * We ended by seeing the end of the string. Make sure we 306 | * have no partial bytes lying around. 307 | */ 308 | if (state != 0) 309 | return (-1); 310 | } 311 | 312 | return (tarindex); 313 | } 314 | -------------------------------------------------------------------------------- /src/libscrypt/b64.h: -------------------------------------------------------------------------------- 1 | 2 | /* BASE64 libraries used internally - should not need to be packaged */ 3 | 4 | #define b64_encode_len(A) ((A+2)/3 * 4 + 1) 5 | #define b64_decode_len(A) (A / 4 * 3 + 2) 6 | 7 | int libscrypt_b64_encode(unsigned char const *src, size_t srclength, 8 | /*@out@*/ char *target, size_t targetsize); 9 | int libscrypt_b64_decode(char const *src, /*@out@*/ unsigned char *target, 10 | size_t targetsize); 11 | -------------------------------------------------------------------------------- /src/libscrypt/crypto-mcf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */ 10 | #include 11 | #endif 12 | 13 | #include "libscrypt.h" 14 | 15 | /* ilog2 for powers of two */ 16 | static uint32_t scrypt_ilog2(uint32_t n) 17 | { 18 | #ifndef S_SPLINT_S 19 | 20 | /* Check for a valid power of two */ 21 | if (n < 2 || (n & (n - 1))) 22 | return -1; 23 | #endif 24 | uint32_t t = 1; 25 | while (((uint32_t)1 << t) < n) 26 | { 27 | if(t > SCRYPT_SAFE_N) 28 | return (uint32_t) -1; /* Check for insanity */ 29 | t++; 30 | } 31 | 32 | return t; 33 | } 34 | 35 | #ifdef _MSC_VER 36 | #define SNPRINTF _snprintf 37 | #else 38 | #define SNPRINTF snprintf 39 | #endif 40 | 41 | int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt, 42 | const char *hash, char *mcf) 43 | { 44 | 45 | uint32_t t, params; 46 | int s; 47 | 48 | if(!mcf || !hash) 49 | return 0; 50 | /* Although larger values of r, p are valid in scrypt, this mcf format 51 | * limits to 8 bits. If your number is larger, current computers will 52 | * struggle 53 | */ 54 | if(r > (uint8_t)(-1) || p > (uint8_t)(-1)) 55 | return 0; 56 | 57 | t = scrypt_ilog2(N); 58 | if (t < 1) 59 | return 0; 60 | 61 | params = (r << 8) + p; 62 | params += (uint32_t)t << 16; 63 | 64 | /* Using snprintf - not checking for overflows. We've already 65 | * determined that mcf should be defined as at least SCRYPT_MCF_LEN 66 | * in length 67 | */ 68 | s = SNPRINTF(mcf, SCRYPT_MCF_LEN, SCRYPT_MCF_ID "$%06x$%s$%s", (unsigned int)params, salt, hash); 69 | if (s > SCRYPT_MCF_LEN) 70 | return 0; 71 | 72 | return 1; 73 | } 74 | -------------------------------------------------------------------------------- /src/libscrypt/crypto-scrypt-saltgen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */ 8 | #include 9 | #endif 10 | 11 | #define RNGDEV "/dev/urandom" 12 | 13 | int libscrypt_salt_gen(uint8_t *salt, size_t len) 14 | { 15 | unsigned char buf[len]; 16 | size_t data_read = 0; 17 | int urandom = open(RNGDEV, O_RDONLY); 18 | 19 | if (urandom < 0) 20 | { 21 | return -1; 22 | } 23 | 24 | while (data_read < len) { 25 | ssize_t result = read(urandom, buf + data_read, len - data_read); 26 | 27 | if (result < 0) 28 | { 29 | if (errno == EINTR || errno == EAGAIN) { 30 | continue; 31 | } 32 | 33 | else { 34 | (void)close(urandom); 35 | return -1; 36 | } 37 | } 38 | 39 | data_read += result; 40 | } 41 | 42 | /* Failures on close() shouldn't occur with O_RDONLY */ 43 | (void)close(urandom); 44 | 45 | memcpy(salt, buf, len); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /src/libscrypt/crypto_scrypt-check.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "b64.h" 7 | #include "slowequals.h" 8 | #include "libscrypt.h" 9 | 10 | #ifdef _WIN32 11 | /* On windows, strtok uses a thread-local static variable in strtok to 12 | * make strtok thread-safe. It also neglects to provide a strtok_r. */ 13 | #define strtok_r(str, val, saveptr) strtok((str), (val)) 14 | #endif 15 | 16 | int libscrypt_check(char *mcf, const char *password) 17 | { 18 | /* Return values: 19 | * <0 error 20 | * == 0 password incorrect 21 | * >0 correct password 22 | */ 23 | 24 | #ifndef _WIN32 25 | char *saveptr = NULL; 26 | #endif 27 | uint32_t params; 28 | uint64_t N; 29 | uint8_t r, p; 30 | int retval; 31 | uint8_t hashbuf[64]; 32 | char outbuf[128]; 33 | uint8_t salt[32]; 34 | char *tok; 35 | 36 | if(memcmp(mcf, SCRYPT_MCF_ID, 3) != 0) 37 | { 38 | /* Only version 0 supported */ 39 | return -1; 40 | } 41 | 42 | tok = strtok_r(mcf, "$", &saveptr); 43 | if ( !tok ) 44 | return -1; 45 | 46 | tok = strtok_r(NULL, "$", &saveptr); 47 | 48 | if ( !tok ) 49 | return -1; 50 | 51 | params = (uint32_t)strtoul(tok, NULL, 16); 52 | if ( params == 0 ) 53 | return -1; 54 | 55 | tok = strtok_r(NULL, "$", &saveptr); 56 | 57 | if ( !tok ) 58 | return -1; 59 | 60 | p = params & 0xff; 61 | r = (params >> 8) & 0xff; 62 | N = params >> 16; 63 | 64 | if (N > SCRYPT_SAFE_N) 65 | return -1; 66 | 67 | N = (uint64_t)1 << N; 68 | 69 | /* Useful debugging: 70 | printf("We've obtained salt 'N' r p of '%s' %d %d %d\n", tok, N,r,p); 71 | */ 72 | 73 | memset(salt, 0, sizeof(salt)); /* Keeps splint happy */ 74 | retval = libscrypt_b64_decode(tok, (unsigned char*)salt, sizeof(salt)); 75 | if (retval < 1) 76 | return -1; 77 | 78 | retval = libscrypt_scrypt((uint8_t*)password, strlen(password), salt, 79 | (uint32_t)retval, N, r, p, hashbuf, sizeof(hashbuf)); 80 | 81 | if (retval != 0) 82 | return -1; 83 | 84 | retval = libscrypt_b64_encode((unsigned char*)hashbuf, sizeof(hashbuf), 85 | outbuf, sizeof(outbuf)); 86 | 87 | if (retval == 0) 88 | return -1; 89 | 90 | tok = strtok_r(NULL, "$", &saveptr); 91 | 92 | if ( !tok ) 93 | return -1; 94 | 95 | if(slow_equals(tok, outbuf) == 0) 96 | { 97 | return 0; 98 | } 99 | 100 | return 1; /* This is the "else" condition */ 101 | } 102 | 103 | -------------------------------------------------------------------------------- /src/libscrypt/crypto_scrypt-hash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "b64.h" 7 | #include "libscrypt.h" 8 | 9 | int libscrypt_hash(char *dst, const char *passphrase, uint32_t N, uint8_t r, 10 | uint8_t p) 11 | { 12 | 13 | int retval; 14 | uint8_t salt[SCRYPT_SALT_LEN]; 15 | uint8_t hashbuf[SCRYPT_HASH_LEN]; 16 | char outbuf[256]; 17 | char saltbuf[256]; 18 | 19 | if(libscrypt_salt_gen(salt, SCRYPT_SALT_LEN) == -1) 20 | { 21 | return 0; 22 | } 23 | 24 | retval = libscrypt_scrypt((const uint8_t*)passphrase, strlen(passphrase), 25 | (uint8_t*)salt, SCRYPT_SALT_LEN, N, r, p, hashbuf, sizeof(hashbuf)); 26 | if(retval == -1) 27 | return 0; 28 | 29 | retval = libscrypt_b64_encode((unsigned char*)hashbuf, sizeof(hashbuf), 30 | outbuf, sizeof(outbuf)); 31 | if(retval == -1) 32 | return 0; 33 | 34 | retval = libscrypt_b64_encode((unsigned char *)salt, sizeof(salt), 35 | saltbuf, sizeof(saltbuf)); 36 | if(retval == -1) 37 | return 0; 38 | 39 | retval = libscrypt_mcf(N, r, p, saltbuf, outbuf, dst); 40 | if(retval != 1) 41 | return 0; 42 | 43 | return 1; 44 | } 45 | -------------------------------------------------------------------------------- /src/libscrypt/crypto_scrypt-hexconvert.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* The hexconvert function is only used to test reference vectors against 7 | * known answers. The contents of this file are therefore a component 8 | * to assist with test harnesses only 9 | */ 10 | 11 | int libscrypt_hexconvert(uint8_t *buf, size_t s, char *outbuf, size_t obs) 12 | { 13 | 14 | size_t i; 15 | int len = 0; 16 | 17 | if (!buf || s < 1 || obs < (s * 2 + 1)) 18 | return 0; 19 | 20 | memset(outbuf, 0, obs); 21 | 22 | 23 | for(i=0; i<=(s-1); i++) 24 | { 25 | /* snprintf(outbuf, s,"%s...", outbuf....) has undefined results 26 | * and can't be used. Using offests like this makes snprintf 27 | * nontrivial. we therefore have use inescure sprintf() and 28 | * lengths checked elsewhere (start of function) */ 29 | /*@ -bufferoverflowhigh @*/ 30 | len += sprintf(outbuf+len, "%02x", (unsigned int) buf[i]); 31 | } 32 | 33 | return 1; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/libscrypt/crypto_scrypt-hexconvert.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | /** 5 | * Converts a binary string to a hex representation of that string 6 | * outbuf must have size of at least buf * 2 + 1. 7 | */ 8 | int libscrypt_hexconvert(const uint8_t *buf, size_t s, char *outbuf, 9 | size_t obs); 10 | -------------------------------------------------------------------------------- /src/libscrypt/crypto_scrypt-nosse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "sha256.h" 36 | #include "sysendian.h" 37 | 38 | #include "libscrypt.h" 39 | 40 | static void blkcpy(uint8_t *, uint8_t *, size_t); 41 | static void blkxor(uint8_t *, uint8_t *, size_t); 42 | static void salsa20_8(uint8_t[64]); 43 | static void blockmix_salsa8(uint8_t *, uint8_t *, size_t); 44 | static uint64_t integerify(uint8_t *, size_t); 45 | static void smix(uint8_t *, size_t, uint64_t, uint8_t *, uint8_t *); 46 | 47 | static void 48 | blkcpy(uint8_t * dest, uint8_t * src, size_t len) 49 | { 50 | size_t i; 51 | 52 | for (i = 0; i < len; i++) 53 | dest[i] = src[i]; 54 | } 55 | 56 | static void 57 | blkxor(uint8_t * dest, uint8_t * src, size_t len) 58 | { 59 | size_t i; 60 | 61 | for (i = 0; i < len; i++) 62 | dest[i] ^= src[i]; 63 | } 64 | 65 | /** 66 | * salsa20_8(B): 67 | * Apply the salsa20/8 core to the provided block. 68 | */ 69 | static void 70 | salsa20_8(uint8_t B[64]) 71 | { 72 | uint32_t B32[16]; 73 | uint32_t x[16]; 74 | size_t i; 75 | 76 | /* Convert little-endian values in. */ 77 | for (i = 0; i < 16; i++) 78 | B32[i] = le32dec(&B[i * 4]); 79 | 80 | /* Compute x = doubleround^4(B32). */ 81 | for (i = 0; i < 16; i++) 82 | x[i] = B32[i]; 83 | for (i = 0; i < 8; i += 2) { 84 | #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) 85 | /* Operate on columns. */ 86 | x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); 87 | x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); 88 | 89 | x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); 90 | x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); 91 | 92 | x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); 93 | x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); 94 | 95 | x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); 96 | x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); 97 | 98 | /* Operate on rows. */ 99 | x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); 100 | x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); 101 | 102 | x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); 103 | x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); 104 | 105 | x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); 106 | x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); 107 | 108 | x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); 109 | x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); 110 | #undef R 111 | } 112 | 113 | /* Compute B32 = B32 + x. */ 114 | for (i = 0; i < 16; i++) 115 | B32[i] += x[i]; 116 | 117 | /* Convert little-endian values out. */ 118 | for (i = 0; i < 16; i++) 119 | le32enc(&B[4 * i], B32[i]); 120 | } 121 | 122 | /** 123 | * blockmix_salsa8(B, Y, r): 124 | * Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in 125 | * length; the temporary space Y must also be the same size. 126 | */ 127 | static void 128 | blockmix_salsa8(uint8_t * B, uint8_t * Y, size_t r) 129 | { 130 | uint8_t X[64]; 131 | size_t i; 132 | 133 | /* 1: X <-- B_{2r - 1} */ 134 | blkcpy(X, &B[(2 * r - 1) * 64], 64); 135 | 136 | /* 2: for i = 0 to 2r - 1 do */ 137 | for (i = 0; i < 2 * r; i++) { 138 | /* 3: X <-- H(X \xor B_i) */ 139 | blkxor(X, &B[i * 64], 64); 140 | salsa20_8(X); 141 | 142 | /* 4: Y_i <-- X */ 143 | blkcpy(&Y[i * 64], X, 64); 144 | } 145 | 146 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 147 | for (i = 0; i < r; i++) 148 | blkcpy(&B[i * 64], &Y[(i * 2) * 64], 64); 149 | for (i = 0; i < r; i++) 150 | blkcpy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64); 151 | } 152 | 153 | /** 154 | * integerify(B, r): 155 | * Return the result of parsing B_{2r-1} as a little-endian integer. 156 | */ 157 | static uint64_t 158 | integerify(uint8_t * B, size_t r) 159 | { 160 | uint8_t * X = &B[(2 * r - 1) * 64]; 161 | 162 | return (le64dec(X)); 163 | } 164 | 165 | /** 166 | * smix(B, r, N, V, XY): 167 | * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; the 168 | * temporary storage V must be 128rN bytes in length; the temporary storage 169 | * XY must be 256r bytes in length. The value N must be a power of 2. 170 | */ 171 | static void 172 | smix(uint8_t * B, size_t r, uint64_t N, uint8_t * V, uint8_t * XY) 173 | { 174 | uint8_t * X = XY; 175 | uint8_t * Y = &XY[128 * r]; 176 | uint64_t i; 177 | uint64_t j; 178 | 179 | /* 1: X <-- B */ 180 | blkcpy(X, B, 128 * r); 181 | 182 | /* 2: for i = 0 to N - 1 do */ 183 | for (i = 0; i < N; i++) { 184 | /* 3: V_i <-- X */ 185 | blkcpy(&V[i * (128 * r)], X, 128 * r); 186 | 187 | /* 4: X <-- H(X) */ 188 | blockmix_salsa8(X, Y, r); 189 | } 190 | 191 | /* 6: for i = 0 to N - 1 do */ 192 | for (i = 0; i < N; i++) { 193 | /* 7: j <-- Integerify(X) mod N */ 194 | j = integerify(X, r) & (N - 1); 195 | 196 | /* 8: X <-- H(X \xor V_j) */ 197 | blkxor(X, &V[j * (128 * r)], 128 * r); 198 | blockmix_salsa8(X, Y, r); 199 | } 200 | 201 | /* 10: B' <-- X */ 202 | blkcpy(B, X, 128 * r); 203 | } 204 | 205 | /** 206 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 207 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 208 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 209 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 210 | * must be a power of 2. 211 | * 212 | * Return 0 on success; or -1 on error. 213 | */ 214 | int 215 | libscrypt_scrypt(const uint8_t * passwd, size_t passwdlen, 216 | const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p, 217 | uint8_t * buf, size_t buflen) 218 | { 219 | uint8_t * B; 220 | uint8_t * V; 221 | uint8_t * XY; 222 | size_t r = _r, p = _p; 223 | uint32_t i; 224 | 225 | /* Sanity-check parameters. */ 226 | #if SIZE_MAX > UINT32_MAX 227 | if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { 228 | errno = EFBIG; 229 | goto err0; 230 | } 231 | #endif 232 | if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { 233 | errno = EFBIG; 234 | goto err0; 235 | } 236 | if (((N & (N - 1)) != 0) || (N == 0)) { 237 | errno = EINVAL; 238 | goto err0; 239 | } 240 | if ((r > SIZE_MAX / 128 / p) || 241 | #if SIZE_MAX / 256 <= UINT32_MAX 242 | (r > SIZE_MAX / 256) || 243 | #endif 244 | (N > SIZE_MAX / 128 / r)) { 245 | errno = ENOMEM; 246 | goto err0; 247 | } 248 | 249 | /* Allocate memory. */ 250 | if ((B = malloc(128 * r * p)) == NULL) 251 | goto err0; 252 | if ((XY = malloc(256 * r)) == NULL) 253 | goto err1; 254 | if ((V = malloc(128 * r * N)) == NULL) 255 | goto err2; 256 | 257 | /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ 258 | libscrypt_PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); 259 | 260 | /* 2: for i = 0 to p - 1 do */ 261 | for (i = 0; i < p; i++) { 262 | /* 3: B_i <-- MF(B_i, N) */ 263 | smix(&B[i * 128 * r], r, N, V, XY); 264 | } 265 | 266 | /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ 267 | libscrypt_PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); 268 | 269 | /* Free memory. */ 270 | free(V); 271 | free(XY); 272 | free(B); 273 | 274 | /* Success! */ 275 | return (0); 276 | 277 | err2: 278 | free(XY); 279 | err1: 280 | free(B); 281 | err0: 282 | /* Failure! */ 283 | return (-1); 284 | } -------------------------------------------------------------------------------- /src/libscrypt/libscrypt.h: -------------------------------------------------------------------------------- 1 | /*- 2 | */ 3 | #ifndef _CRYPTO_SCRYPT_H_ 4 | #define _CRYPTO_SCRYPT_H_ 5 | 6 | 7 | #include 8 | #include "android.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C"{ 12 | #endif 13 | 14 | /** 15 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 16 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 17 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 18 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 19 | * must be a power of 2 greater than 1. 20 | * 21 | * libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 22 | * password; duh 23 | * N: CPU AND RAM cost (first modifier) 24 | * r: RAM Cost 25 | * p: CPU cost (parallelisation) 26 | * In short, N is your main performance modifier. Values of r = 8, p = 1 are 27 | * standard unless you want to modify the CPU/RAM ratio. 28 | * Return 0 on success; or -1 on error. 29 | */ 30 | int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, 31 | uint32_t, uint32_t, /*@out@*/ uint8_t *, size_t); 32 | 33 | /* Converts a series of input parameters to a MCF form for storage */ 34 | int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt, 35 | const char *hash, char *mcf); 36 | 37 | #ifndef _MSC_VER 38 | /* Generates a salt. Uses /dev/urandom/ 39 | */ 40 | int libscrypt_salt_gen(/*@out@*/ uint8_t *rand, size_t len); 41 | 42 | /* Creates a hash of a passphrase using a randomly generated salt */ 43 | /* Returns >0 on success, or 0 for fail */ 44 | int libscrypt_hash(char *dst, const char* passphrase, uint32_t N, uint8_t r, 45 | uint8_t p); 46 | #endif 47 | 48 | /* Checks a given MCF against a password */ 49 | int libscrypt_check(char *mcf, const char *password); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | /* Sane default values */ 56 | #define SCRYPT_HASH_LEN 64 /* This can be user defined - 57 | *but 64 is the reference size 58 | */ 59 | #define SCRYPT_SAFE_N 30 /* This is much higher than you want. It's just 60 | * a blocker for insane defines 61 | */ 62 | #define SCRYPT_SALT_LEN 16 /* This is just a recommended size */ 63 | #define SCRYPT_MCF_LEN 125 /* mcf is 120 byte + nul */ 64 | #define SCRYPT_MCF_ID "$s1" 65 | #define SCRYPT_N 16384 66 | #define SCRYPT_r 8 67 | #define SCRYPT_p 16 68 | #endif /* !_CRYPTO_SCRYPT_H_ */ 69 | -------------------------------------------------------------------------------- /src/libscrypt/libscrypt.version: -------------------------------------------------------------------------------- 1 | libscrypt { 2 | global: libscrypt_check; 3 | libscrypt_hash; 4 | libscrypt_mcf; 5 | libscrypt_salt_gen; 6 | libscrypt_scrypt; 7 | local: *; 8 | }; 9 | -------------------------------------------------------------------------------- /src/libscrypt/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "b64.h" 7 | #include "crypto_scrypt-hexconvert.h" 8 | #include "libscrypt.h" 9 | 10 | #define REF1 "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640" 11 | 12 | #define REF2 "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887" 13 | 14 | 15 | int main() 16 | { 17 | uint8_t hashbuf[SCRYPT_HASH_LEN]; 18 | char outbuf[132]; 19 | char mcf[SCRYPT_MCF_LEN]; 20 | char mcf2[SCRYPT_MCF_LEN]; 21 | char saltbuf[64]; 22 | int retval; 23 | /** 24 | * libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 25 | * password; duh 26 | * N: CPU AND RAM cost (first modifier) 27 | * r: RAM Cost 28 | * p: CPU cost (parallelisation) 29 | * In short, N is your main performance modifier. Values of r = 8, p = 1 are 30 | * standard unless you want to modify the CPU/RAM ratio. 31 | int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, 32 | uint32_t, uint32_t, uint8_t *, size_t); 33 | */ 34 | 35 | printf("TEST ONE: Direct call to reference function with password 'password' and salt 'NaCL'\n"); 36 | 37 | retval = libscrypt_scrypt((uint8_t*)"password",strlen("password"), (uint8_t*)"NaCl", strlen("NaCl"), 1024, 8, 16, hashbuf, sizeof(hashbuf)); 38 | 39 | if(retval != 0) 40 | { 41 | printf("TEST ONE FAILED: Failed to create hash of \"password\"\\n"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | printf("TEST ONE: SUCCESSFUL\n"); 46 | 47 | printf("TEST ONE and a half: Review errno on invalid input\n"); 48 | 49 | retval = libscrypt_scrypt((uint8_t*)"password",strlen("password"), (uint8_t*)"NaCl", strlen("NaCl"), 47, 1, 1, hashbuf, sizeof(hashbuf)); 50 | 51 | if(retval != -1) 52 | { 53 | printf("TEST ONE FAILED: Failed to detect invalid input\n"); 54 | exit(EXIT_FAILURE); 55 | } 56 | printf("TEST ONE and a half: Successfully failed on error: %s\n", strerror(errno)); 57 | 58 | /* Convert the binary string to hex representation. Outbuf must be 59 | * at least sizeof(hashbuf) * 2 + 1 60 | * Returns 0 on fail, 1 on success 61 | */ 62 | printf("TEST TWO: Convert binary output to hex\n"); 63 | retval = libscrypt_hexconvert(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); 64 | if(!retval) 65 | { 66 | printf("TEST TWO: FAILED\n"); 67 | exit(EXIT_FAILURE); 68 | } 69 | printf("TEST TWO: SUCCESSFUL, Hex output is:\n%s\n", outbuf); 70 | 71 | printf("TEST THREE: Compare hex output to reference hash output\n"); 72 | 73 | /* REF1 is a reference vector from Colin's implementation. */ 74 | if(strcmp(outbuf, REF1) != 0) 75 | { 76 | printf("TEST THREE: FAILED to match reference on hash\n"); 77 | exit(EXIT_FAILURE); 78 | } 79 | else 80 | { 81 | printf("TEST THREE: SUCCESSUL, Test vector matched!\n"); 82 | } 83 | 84 | printf("TEST FOUR: Direct call to reference function with pleaseletmein password and SodiumChloride as salt\n"); 85 | 86 | /* Tests 4-6 repeat tests 1-3 with a different reference vector */ 87 | 88 | retval = libscrypt_scrypt((uint8_t*)"pleaseletmein",strlen("pleaseletmein"), (uint8_t*)"SodiumChloride", strlen("SodiumChloride"), 16384, 8, 1, hashbuf, sizeof(hashbuf)); 89 | 90 | if(retval != 0) 91 | { 92 | printf("TEST FOUR FAILED: Failed to create hash of 'pleaseletmein'\n"); 93 | exit(EXIT_FAILURE); 94 | } 95 | 96 | printf("TEST FOUR: SUCCESSFUL\n"); 97 | 98 | /* Convert the binary string to hex representation. Outbuf must be 99 | * at least sizeof(hashbuf) * 2 + 1 100 | */ 101 | printf("TEST FIVE: Convert binary output to hex\n"); 102 | retval = libscrypt_hexconvert(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); 103 | if(!retval) 104 | { 105 | printf("TEST FIVE: FAILED\n"); 106 | exit(EXIT_FAILURE); 107 | } 108 | printf("TEST FIVE: SUCCESSFUL, Hex output is:\n%s\n", outbuf); 109 | 110 | printf("TEST SIX: Compare hex output to reference hash output\n"); 111 | 112 | if(strcmp(outbuf, REF2) != 0) 113 | { 114 | printf("TEST SIX: FAILED to match reference on hash\n"); 115 | exit(EXIT_FAILURE); 116 | } 117 | else 118 | { 119 | printf("TEST SIX: SUCCESSUL, Test vector matched!\n"); 120 | } 121 | 122 | /* This function will convert the binary output to BASE64. Although 123 | * we converted to hex for the reference vectors, BASE64 is more useful. 124 | * Returns -1 on error, else returns length. 125 | * Correct buffer length can be determined using the below function if 126 | retuired. 127 | * char* dest = (char*) malloc(modp_b64_encode_len); 128 | * Note that this is not an exported function 129 | */ 130 | 131 | printf("TEST SEVEN: BASE64 encoding the salt and hash output\n"); 132 | 133 | retval = libscrypt_b64_encode(hashbuf, sizeof(hashbuf), outbuf, sizeof(outbuf)); 134 | if(retval == -1) 135 | { 136 | printf("TEST SEVEN FAILED\n"); 137 | exit(EXIT_FAILURE); 138 | } 139 | retval = libscrypt_b64_encode((unsigned char*)"SodiumChloride", strlen("SodiumChloride"), saltbuf, sizeof(saltbuf)); 140 | if(retval == -1) 141 | { 142 | printf("TEST SEVEN FAILED\n"); 143 | exit(EXIT_FAILURE); 144 | } 145 | 146 | printf("TEST SEVEN: SUCCESSFUL\n"); 147 | 148 | printf("TEST EIGHT: Create an MCF format output\n"); 149 | 150 | /* Creates a standard format output 151 | * int crypto_scrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, char *mcf); 152 | * Returns 0 on error, most likely reason is log2(N) not an integer. 153 | */ 154 | retval = libscrypt_mcf(16384, 8, 1, saltbuf, outbuf, mcf); 155 | if(!retval) 156 | { 157 | printf("TEST EIGHT FAILED\n"); 158 | exit(EXIT_FAILURE); 159 | } 160 | 161 | printf("TEST EIGHT: SUCCESSFUL, calculated mcf\n%s\n", mcf); 162 | 163 | /* Since later calls to scrypt_check() butcher mcf, make a second */ 164 | strcpy(mcf2, mcf); 165 | 166 | /* Couldn't be simpler - for a given mcf, check is the password is valid 167 | * Returns < 0 on failure to calculate hash 168 | * 0 if password incorrect 169 | * >1 if password correct 170 | */ 171 | 172 | printf("TEST NINE: Password verify on given MCF\n"); 173 | retval = libscrypt_check(mcf, "pleaseletmein"); 174 | 175 | if(retval < 0) 176 | { 177 | printf("TEST NINE: FAILED, hash failed to calculate\n"); 178 | exit(EXIT_FAILURE); 179 | } 180 | if(retval == 0) 181 | { 182 | printf("TEST NINE: FAILED, claimed pleaseletmein hash claimed did not verify\n"); 183 | exit(EXIT_FAILURE); 184 | } 185 | /* retval >0 is a success */ 186 | printf("TEST NINE: SUCCESSFUL, tested pleaseletmein password\n"); 187 | 188 | printf("TEST TEN: Password verify on same MCF, incorrect password\n"); 189 | retval = libscrypt_check(mcf2, "pleasefailme"); 190 | 191 | if(retval < 0) 192 | { 193 | printf("TEST TEN: FAILED, hash failed to calculate\n"); 194 | exit(EXIT_FAILURE); 195 | } 196 | if(retval > 0) 197 | { 198 | printf("TEST TEN: FAILED, fail hash has passed\n"); 199 | exit(EXIT_FAILURE); 200 | } 201 | 202 | printf("TEST TEN: SUCCESSFUL, refused incorrect password\n"); 203 | 204 | printf("TEST ELEVEN: Testing salt generator\n"); 205 | 206 | retval = libscrypt_salt_gen((uint8_t*)saltbuf, SCRYPT_SALT_LEN); 207 | if(retval == -1) 208 | { 209 | printf("TEST ELEVEN (salt generate) FAILED\n"); 210 | exit(EXIT_FAILURE); 211 | } 212 | 213 | retval = libscrypt_b64_encode((uint8_t*)saltbuf, SCRYPT_SALT_LEN, outbuf, sizeof(outbuf)); 214 | if(retval == -1) 215 | { 216 | printf("TEST ELEVEN (b64 encode) FAILED\n"); 217 | exit(EXIT_FAILURE); 218 | } 219 | printf("TEST ELEVEN: SUCCESSFUL, Generated %s\n", outbuf); 220 | 221 | printf("TEST TWELVE: Simple hash creation\n"); 222 | 223 | retval = libscrypt_hash(outbuf, "My cats's breath smells like cat food", SCRYPT_N, SCRYPT_r, SCRYPT_p); 224 | if(!retval) 225 | { 226 | printf("TEST TWELVE: FAILED, Failed to create simple hash\n"); 227 | exit(EXIT_FAILURE); 228 | } 229 | printf("TEST TWELVE: SUCCESSFUL. Received the following from simple hash:\n%s\n", outbuf); 230 | 231 | printf("TEST THIRTEEN: Verify test twelve's hash\n"); 232 | 233 | retval = libscrypt_check(outbuf, "My cats's breath smells like cat food"); 234 | 235 | if (retval != 1) { 236 | printf("TEST THIRTEEN: FAILED, hash not verified\n"); 237 | exit(EXIT_FAILURE); 238 | } 239 | 240 | printf("TEST THIRTEEN: SUCCESSFUL\n"); 241 | 242 | return 0; 243 | } 244 | 245 | -------------------------------------------------------------------------------- /src/libscrypt/sha256.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2005,2007,2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #include "sysendian.h" 33 | 34 | #include "sha256.h" 35 | 36 | /* 37 | * Encode a length len/4 vector of (uint32_t) into a length len vector of 38 | * (unsigned char) in big-endian form. Assumes len is a multiple of 4. 39 | */ 40 | static void 41 | be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) 42 | { 43 | size_t i; 44 | 45 | for (i = 0; i < len / 4; i++) 46 | be32enc(dst + i * 4, src[i]); 47 | } 48 | 49 | /* 50 | * Decode a big-endian length len vector of (unsigned char) into a length 51 | * len/4 vector of (uint32_t). Assumes len is a multiple of 4. 52 | */ 53 | static void 54 | be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) 55 | { 56 | size_t i; 57 | 58 | for (i = 0; i < len / 4; i++) 59 | dst[i] = be32dec(src + i * 4); 60 | } 61 | 62 | /* Elementary functions used by SHA256 */ 63 | #define Ch(x, y, z) ((x & (y ^ z)) ^ z) 64 | #define Maj(x, y, z) ((x & (y | z)) | (y & z)) 65 | #define SHR(x, n) (x >> n) 66 | #define ROTR(x, n) ((x >> n) | (x << (32 - n))) 67 | #define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) 68 | #define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) 69 | #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) 70 | #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) 71 | 72 | /* SHA256 round function */ 73 | #define RND(a, b, c, d, e, f, g, h, k) \ 74 | t0 = h + S1(e) + Ch(e, f, g) + k; \ 75 | t1 = S0(a) + Maj(a, b, c); \ 76 | d += t0; \ 77 | h = t0 + t1; 78 | 79 | /* Adjusted round function for rotating state */ 80 | #define RNDr(S, W, i, k) \ 81 | RND(S[(64 - i) % 8], S[(65 - i) % 8], \ 82 | S[(66 - i) % 8], S[(67 - i) % 8], \ 83 | S[(68 - i) % 8], S[(69 - i) % 8], \ 84 | S[(70 - i) % 8], S[(71 - i) % 8], \ 85 | W[i] + k) 86 | 87 | /* 88 | * SHA256 block compression function. The 256-bit state is transformed via 89 | * the 512-bit input block to produce a new state. 90 | */ 91 | static void 92 | SHA256_Transform(uint32_t * state, const unsigned char block[64]) 93 | { 94 | uint32_t W[64]; 95 | uint32_t S[8]; 96 | uint32_t t0, t1; 97 | int i; 98 | 99 | /* 1. Prepare message schedule W. */ 100 | be32dec_vect(W, block, 64); 101 | for (i = 16; i < 64; i++) 102 | W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; 103 | 104 | /* 2. Initialize working variables. */ 105 | memcpy(S, state, 32); 106 | 107 | /* 3. Mix. */ 108 | RNDr(S, W, 0, 0x428a2f98); 109 | RNDr(S, W, 1, 0x71374491); 110 | RNDr(S, W, 2, 0xb5c0fbcf); 111 | RNDr(S, W, 3, 0xe9b5dba5); 112 | RNDr(S, W, 4, 0x3956c25b); 113 | RNDr(S, W, 5, 0x59f111f1); 114 | RNDr(S, W, 6, 0x923f82a4); 115 | RNDr(S, W, 7, 0xab1c5ed5); 116 | RNDr(S, W, 8, 0xd807aa98); 117 | RNDr(S, W, 9, 0x12835b01); 118 | RNDr(S, W, 10, 0x243185be); 119 | RNDr(S, W, 11, 0x550c7dc3); 120 | RNDr(S, W, 12, 0x72be5d74); 121 | RNDr(S, W, 13, 0x80deb1fe); 122 | RNDr(S, W, 14, 0x9bdc06a7); 123 | RNDr(S, W, 15, 0xc19bf174); 124 | RNDr(S, W, 16, 0xe49b69c1); 125 | RNDr(S, W, 17, 0xefbe4786); 126 | RNDr(S, W, 18, 0x0fc19dc6); 127 | RNDr(S, W, 19, 0x240ca1cc); 128 | RNDr(S, W, 20, 0x2de92c6f); 129 | RNDr(S, W, 21, 0x4a7484aa); 130 | RNDr(S, W, 22, 0x5cb0a9dc); 131 | RNDr(S, W, 23, 0x76f988da); 132 | RNDr(S, W, 24, 0x983e5152); 133 | RNDr(S, W, 25, 0xa831c66d); 134 | RNDr(S, W, 26, 0xb00327c8); 135 | RNDr(S, W, 27, 0xbf597fc7); 136 | RNDr(S, W, 28, 0xc6e00bf3); 137 | RNDr(S, W, 29, 0xd5a79147); 138 | RNDr(S, W, 30, 0x06ca6351); 139 | RNDr(S, W, 31, 0x14292967); 140 | RNDr(S, W, 32, 0x27b70a85); 141 | RNDr(S, W, 33, 0x2e1b2138); 142 | RNDr(S, W, 34, 0x4d2c6dfc); 143 | RNDr(S, W, 35, 0x53380d13); 144 | RNDr(S, W, 36, 0x650a7354); 145 | RNDr(S, W, 37, 0x766a0abb); 146 | RNDr(S, W, 38, 0x81c2c92e); 147 | RNDr(S, W, 39, 0x92722c85); 148 | RNDr(S, W, 40, 0xa2bfe8a1); 149 | RNDr(S, W, 41, 0xa81a664b); 150 | RNDr(S, W, 42, 0xc24b8b70); 151 | RNDr(S, W, 43, 0xc76c51a3); 152 | RNDr(S, W, 44, 0xd192e819); 153 | RNDr(S, W, 45, 0xd6990624); 154 | RNDr(S, W, 46, 0xf40e3585); 155 | RNDr(S, W, 47, 0x106aa070); 156 | RNDr(S, W, 48, 0x19a4c116); 157 | RNDr(S, W, 49, 0x1e376c08); 158 | RNDr(S, W, 50, 0x2748774c); 159 | RNDr(S, W, 51, 0x34b0bcb5); 160 | RNDr(S, W, 52, 0x391c0cb3); 161 | RNDr(S, W, 53, 0x4ed8aa4a); 162 | RNDr(S, W, 54, 0x5b9cca4f); 163 | RNDr(S, W, 55, 0x682e6ff3); 164 | RNDr(S, W, 56, 0x748f82ee); 165 | RNDr(S, W, 57, 0x78a5636f); 166 | RNDr(S, W, 58, 0x84c87814); 167 | RNDr(S, W, 59, 0x8cc70208); 168 | RNDr(S, W, 60, 0x90befffa); 169 | RNDr(S, W, 61, 0xa4506ceb); 170 | RNDr(S, W, 62, 0xbef9a3f7); 171 | RNDr(S, W, 63, 0xc67178f2); 172 | 173 | /* 4. Mix local working variables into global state */ 174 | for (i = 0; i < 8; i++) 175 | state[i] += S[i]; 176 | 177 | /* Clean the stack. */ 178 | memset(W, 0, 256); 179 | memset(S, 0, 32); 180 | t0 = t1 = 0; 181 | } 182 | 183 | static unsigned char PAD[64] = { 184 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 188 | }; 189 | 190 | /* Add padding and terminating bit-count. */ 191 | static void 192 | SHA256_Pad(SHA256_CTX * ctx) 193 | { 194 | unsigned char len[8]; 195 | uint32_t r, plen; 196 | 197 | /* 198 | * Convert length to a vector of bytes -- we do this now rather 199 | * than later because the length will change after we pad. 200 | */ 201 | be32enc_vect(len, ctx->count, 8); 202 | 203 | /* Add 1--64 bytes so that the resulting length is 56 mod 64 */ 204 | r = (ctx->count[1] >> 3) & 0x3f; 205 | plen = (r < 56) ? (56 - r) : (120 - r); 206 | libscrypt_SHA256_Update(ctx, PAD, (size_t)plen); 207 | 208 | /* Add the terminating bit-count */ 209 | libscrypt_SHA256_Update(ctx, len, 8); 210 | } 211 | 212 | /* SHA-256 initialization. Begins a SHA-256 operation. */ 213 | void 214 | libscrypt_SHA256_Init(SHA256_CTX * ctx) 215 | { 216 | 217 | /* Zero bits processed so far */ 218 | ctx->count[0] = ctx->count[1] = 0; 219 | 220 | /* Magic initialization constants */ 221 | ctx->state[0] = 0x6A09E667; 222 | ctx->state[1] = 0xBB67AE85; 223 | ctx->state[2] = 0x3C6EF372; 224 | ctx->state[3] = 0xA54FF53A; 225 | ctx->state[4] = 0x510E527F; 226 | ctx->state[5] = 0x9B05688C; 227 | ctx->state[6] = 0x1F83D9AB; 228 | ctx->state[7] = 0x5BE0CD19; 229 | } 230 | 231 | /* Add bytes into the hash */ 232 | void 233 | libscrypt_SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len) 234 | { 235 | uint32_t bitlen[2]; 236 | uint32_t r; 237 | const unsigned char *src = in; 238 | 239 | /* Number of bytes left in the buffer from previous updates */ 240 | r = (ctx->count[1] >> 3) & 0x3f; 241 | 242 | /* Convert the length into a number of bits */ 243 | bitlen[1] = ((uint32_t)len) << 3; 244 | bitlen[0] = (uint32_t)(len >> 29); 245 | 246 | /* Update number of bits */ 247 | if ((ctx->count[1] += bitlen[1]) < bitlen[1]) 248 | ctx->count[0]++; 249 | ctx->count[0] += bitlen[0]; 250 | 251 | /* Handle the case where we don't need to perform any transforms */ 252 | if (len < 64 - r) { 253 | memcpy(&ctx->buf[r], src, len); 254 | return; 255 | } 256 | 257 | /* Finish the current block */ 258 | memcpy(&ctx->buf[r], src, 64 - r); 259 | SHA256_Transform(ctx->state, ctx->buf); 260 | src += 64 - r; 261 | len -= 64 - r; 262 | 263 | /* Perform complete blocks */ 264 | while (len >= 64) { 265 | SHA256_Transform(ctx->state, src); 266 | src += 64; 267 | len -= 64; 268 | } 269 | 270 | /* Copy left over data into buffer */ 271 | memcpy(ctx->buf, src, len); 272 | } 273 | 274 | /* 275 | * SHA-256 finalization. Pads the input data, exports the hash value, 276 | * and clears the context state. 277 | */ 278 | void 279 | libscrypt_SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx) 280 | { 281 | 282 | /* Add padding */ 283 | SHA256_Pad(ctx); 284 | 285 | /* Write the hash */ 286 | be32enc_vect(digest, ctx->state, 32); 287 | 288 | /* Clear the context state */ 289 | memset((void *)ctx, 0, sizeof(*ctx)); 290 | } 291 | 292 | /* Initialize an HMAC-SHA256 operation with the given key. */ 293 | void 294 | libscrypt_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) 295 | { 296 | unsigned char pad[64]; 297 | unsigned char khash[32]; 298 | const unsigned char * K = _K; 299 | size_t i; 300 | 301 | /* If Klen > 64, the key is really SHA256(K). */ 302 | if (Klen > 64) { 303 | libscrypt_SHA256_Init(&ctx->ictx); 304 | libscrypt_SHA256_Update(&ctx->ictx, K, Klen); 305 | libscrypt_SHA256_Final(khash, &ctx->ictx); 306 | K = khash; 307 | Klen = 32; 308 | } 309 | 310 | /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ 311 | libscrypt_SHA256_Init(&ctx->ictx); 312 | memset(pad, 0x36, 64); 313 | for (i = 0; i < Klen; i++) 314 | pad[i] ^= K[i]; 315 | libscrypt_SHA256_Update(&ctx->ictx, pad, 64); 316 | 317 | /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ 318 | libscrypt_SHA256_Init(&ctx->octx); 319 | memset(pad, 0x5c, 64); 320 | for (i = 0; i < Klen; i++) 321 | pad[i] ^= K[i]; 322 | libscrypt_SHA256_Update(&ctx->octx, pad, 64); 323 | 324 | /* Clean the stack. */ 325 | memset(khash, 0, 32); 326 | } 327 | 328 | /* Add bytes to the HMAC-SHA256 operation. */ 329 | void 330 | libscrypt_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) 331 | { 332 | 333 | /* Feed data to the inner SHA256 operation. */ 334 | libscrypt_SHA256_Update(&ctx->ictx, in, len); 335 | } 336 | 337 | /* Finish an HMAC-SHA256 operation. */ 338 | void 339 | libscrypt_HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) 340 | { 341 | unsigned char ihash[32]; 342 | 343 | /* Finish the inner SHA256 operation. */ 344 | libscrypt_SHA256_Final(ihash, &ctx->ictx); 345 | 346 | /* Feed the inner hash to the outer SHA256 operation. */ 347 | libscrypt_SHA256_Update(&ctx->octx, ihash, 32); 348 | 349 | /* Finish the outer SHA256 operation. */ 350 | libscrypt_SHA256_Final(digest, &ctx->octx); 351 | 352 | /* Clean the stack. */ 353 | memset(ihash, 0, 32); 354 | } 355 | 356 | /** 357 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 358 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 359 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 360 | */ 361 | void 362 | libscrypt_PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, 363 | size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) 364 | { 365 | HMAC_SHA256_CTX PShctx, hctx; 366 | size_t i; 367 | uint8_t ivec[4]; 368 | uint8_t U[32]; 369 | uint8_t T[32]; 370 | uint64_t j; 371 | int k; 372 | size_t clen; 373 | 374 | /* Compute HMAC state after processing P and S. */ 375 | libscrypt_HMAC_SHA256_Init(&PShctx, passwd, passwdlen); 376 | libscrypt_HMAC_SHA256_Update(&PShctx, salt, saltlen); 377 | 378 | /* Iterate through the blocks. */ 379 | for (i = 0; i * 32 < dkLen; i++) { 380 | /* Generate INT(i + 1). */ 381 | be32enc(ivec, (uint32_t)(i + 1)); 382 | 383 | /* Compute U_1 = PRF(P, S || INT(i)). */ 384 | memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); 385 | libscrypt_HMAC_SHA256_Update(&hctx, ivec, 4); 386 | libscrypt_HMAC_SHA256_Final(U, &hctx); 387 | 388 | /* T_i = U_1 ... */ 389 | memcpy(T, U, 32); 390 | 391 | for (j = 2; j <= c; j++) { 392 | /* Compute U_j. */ 393 | libscrypt_HMAC_SHA256_Init(&hctx, passwd, passwdlen); 394 | libscrypt_HMAC_SHA256_Update(&hctx, U, 32); 395 | libscrypt_HMAC_SHA256_Final(U, &hctx); 396 | 397 | /* ... xor U_j ... */ 398 | for (k = 0; k < 32; k++) 399 | T[k] ^= U[k]; 400 | } 401 | 402 | /* Copy as many bytes as necessary into buf. */ 403 | clen = dkLen - i * 32; 404 | if (clen > 32) 405 | clen = 32; 406 | memcpy(&buf[i * 32], T, clen); 407 | } 408 | 409 | /* Clean PShctx, since we never called _Final on it. */ 410 | memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); 411 | } 412 | -------------------------------------------------------------------------------- /src/libscrypt/sha256.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2005,2007,2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $ 27 | */ 28 | 29 | #ifndef _SHA256_H_ 30 | #define _SHA256_H_ 31 | 32 | #include 33 | 34 | #include 35 | 36 | typedef struct libscrypt_SHA256Context { 37 | uint32_t state[8]; 38 | uint32_t count[2]; 39 | unsigned char buf[64]; 40 | } SHA256_CTX; 41 | 42 | typedef struct libscrypt_HMAC_SHA256Context { 43 | SHA256_CTX ictx; 44 | SHA256_CTX octx; 45 | } HMAC_SHA256_CTX; 46 | 47 | void libscrypt_SHA256_Init(/*@out@*/ SHA256_CTX *); 48 | void libscrypt_SHA256_Update(SHA256_CTX *, const void *, size_t); 49 | 50 | /* Original declaration: 51 | * void SHA256_Final(unsigned char [32], SHA256_CTX *); 52 | */ 53 | void libscrypt_SHA256_Final(/*@out@*/ unsigned char [], SHA256_CTX *); 54 | void libscrypt_HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); 55 | void libscrypt_HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); 56 | 57 | /* Original declaration: 58 | * void HMAC_SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *); 59 | */ 60 | void libscrypt_HMAC_SHA256_Final(unsigned char [], HMAC_SHA256_CTX *); 61 | 62 | /** 63 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 64 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 65 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 66 | */ 67 | void libscrypt_PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, 68 | uint64_t, uint8_t *, size_t); 69 | 70 | #endif /* !_SHA256_H_ */ 71 | -------------------------------------------------------------------------------- /src/libscrypt/slowequals.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Implements a constant time version of strcmp() 4 | * Will return 1 if a and b are equal, 0 if they are not */ 5 | int slow_equals(const char* a, const char* b) 6 | { 7 | size_t lena, lenb, diff, i; 8 | lena = strlen(a); 9 | lenb = strlen(b); 10 | diff = strlen(a) ^ strlen(b); 11 | 12 | for(i=0; i we have isn't usable. */ 34 | #if !HAVE_DECL_BE64ENC 35 | #undef HAVE_SYS_ENDIAN_H 36 | #endif 37 | 38 | #ifdef HAVE_SYS_ENDIAN_H 39 | 40 | #include 41 | 42 | #else 43 | 44 | #include 45 | #ifdef _MSC_VER 46 | #define INLINE __inline 47 | #else 48 | #define INLINE inline 49 | #endif 50 | 51 | static INLINE uint32_t 52 | be32dec(const void *pp) 53 | { 54 | const uint8_t *p = (uint8_t const *)pp; 55 | 56 | return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + 57 | ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); 58 | } 59 | 60 | static INLINE void 61 | be32enc(void *pp, uint32_t x) 62 | { 63 | uint8_t * p = (uint8_t *)pp; 64 | 65 | p[3] = x & 0xff; 66 | p[2] = (x >> 8) & 0xff; 67 | p[1] = (x >> 16) & 0xff; 68 | p[0] = (x >> 24) & 0xff; 69 | } 70 | 71 | static INLINE uint64_t 72 | be64dec(const void *pp) 73 | { 74 | const uint8_t *p = (uint8_t const *)pp; 75 | 76 | return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + 77 | ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + 78 | ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + 79 | ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); 80 | } 81 | 82 | static INLINE void 83 | be64enc(void *pp, uint64_t x) 84 | { 85 | uint8_t * p = (uint8_t *)pp; 86 | 87 | p[7] = x & 0xff; 88 | p[6] = (x >> 8) & 0xff; 89 | p[5] = (x >> 16) & 0xff; 90 | p[4] = (x >> 24) & 0xff; 91 | p[3] = (x >> 32) & 0xff; 92 | p[2] = (x >> 40) & 0xff; 93 | p[1] = (x >> 48) & 0xff; 94 | p[0] = (x >> 56) & 0xff; 95 | } 96 | 97 | static INLINE uint32_t 98 | le32dec(const void *pp) 99 | { 100 | const uint8_t *p = (uint8_t const *)pp; 101 | 102 | return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + 103 | ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); 104 | } 105 | 106 | static INLINE void 107 | le32enc(void *pp, uint32_t x) 108 | { 109 | uint8_t * p = (uint8_t *)pp; 110 | 111 | p[0] = x & 0xff; 112 | p[1] = (x >> 8) & 0xff; 113 | p[2] = (x >> 16) & 0xff; 114 | p[3] = (x >> 24) & 0xff; 115 | } 116 | 117 | static INLINE uint64_t 118 | le64dec(const void *pp) 119 | { 120 | const uint8_t *p = (uint8_t const *)pp; 121 | 122 | return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) + 123 | ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) + 124 | ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) + 125 | ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56)); 126 | } 127 | 128 | static INLINE void 129 | le64enc(void *pp, uint64_t x) 130 | { 131 | uint8_t * p = (uint8_t *)pp; 132 | 133 | p[0] = x & 0xff; 134 | p[1] = (x >> 8) & 0xff; 135 | p[2] = (x >> 16) & 0xff; 136 | p[3] = (x >> 24) & 0xff; 137 | p[4] = (x >> 32) & 0xff; 138 | p[5] = (x >> 40) & 0xff; 139 | p[6] = (x >> 48) & 0xff; 140 | p[7] = (x >> 56) & 0xff; 141 | } 142 | #endif /* !HAVE_SYS_ENDIAN_H */ 143 | 144 | #endif /* !_SYSENDIAN_H_ */ 145 | -------------------------------------------------------------------------------- /testing.config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Scrypt tests 4 | 5 | 6 | 7 | Crypho AS 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-scrypt-tests", 3 | "version": "1.0.0", 4 | "description": "Tests for cordova-plugin-scrypt", 5 | "author": "Yiorgis Gozadinos ", 6 | "cordova": { 7 | "id": "cordova-plugin-scrypt", 8 | "platforms": [ 9 | "android", 10 | "ios" 11 | ] 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/crypho/cordova-plugin-scrypt.git" 16 | }, 17 | "devDependencies": { 18 | "cordova-plugin-test-framework": ">=1.0.0" 19 | }, 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/crypho/cordova-plugin-scrypt/issues" 23 | }, 24 | "homepage": "https://github.com/crypho/cordova-plugin-scrypt#readme" 25 | } 26 | -------------------------------------------------------------------------------- /tests/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | ScryptPlugin Tests 8 | Crypho AS 9 | 10 | 11 | Test for cordova-plugin-scrypt 12 | 13 | 14 | MIT 15 | 16 | scrypt, encryption, tests 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/tests.js: -------------------------------------------------------------------------------- 1 | var testCases = [ 2 | { 3 | "salt": [207, 45, 55, 220, 196, 92, 83, 32], 4 | "password": "hello", 5 | "p": 1, 6 | "expected": "6907e763e5fd22fcce6f1fa74498b1580cfe8233746c39a0cafae86b9ee34214" 7 | }, 8 | { 9 | "salt": "salt", 10 | "password": "password", 11 | "N": 2, 12 | "r": 1, 13 | "p": 1, 14 | "dkLen": 32, 15 | "expected": "6d1bb878eee9ce4a7b77d7a44103574d4cbfe3c15ae3940f0ffe75cd5e1e0afa" 16 | }, 17 | { 18 | "salt": "salt", 19 | "password": "password", 20 | "N": 2, 21 | "r": 2, 22 | "p": 1, 23 | "dkLen": 32, 24 | "expected": "b6902e4c128feb4b3a475d59773bc4b25e44080cea51d7526b18986c52008386" 25 | }, 26 | { 27 | "salt": "salt", 28 | "password": "password", 29 | "N": 2, 30 | "r": 1, 31 | "p": 1, 32 | "dkLen": 32, 33 | "expected": "6d1bb878eee9ce4a7b77d7a44103574d4cbfe3c15ae3940f0ffe75cd5e1e0afa" 34 | }, 35 | { 36 | "salt": "salt", 37 | "password": "password", 38 | "N": 2, 39 | "r": 1, 40 | "p": 2, 41 | "dkLen": 32, 42 | "expected": "4db52954f6ece830ebef61b6613b9f1dfd921922d32a1af5b719d15a6676e8ad" 43 | }, 44 | { 45 | "salt": "salt", 46 | "password": "password", 47 | "N": 2, 48 | "r": 2, 49 | "p": 1, 50 | "dkLen": 32, 51 | "expected": "b6902e4c128feb4b3a475d59773bc4b25e44080cea51d7526b18986c52008386" 52 | }, 53 | { 54 | "salt": "salt", 55 | "password": "password", 56 | "N": 4, 57 | "r": 1, 58 | "p": 1, 59 | "dkLen": 32, 60 | "expected": "2ef4390d867dcad84fbb1c064e7fe984e1e9850922ac45c11b2f30c85043f9bd" 61 | }, 62 | { 63 | "salt": "salt", 64 | "password": "password", 65 | "N": 2, 66 | "r": 1, 67 | "p": 1, 68 | "dkLen": 48, 69 | "expected": "6d1bb878eee9ce4a7b77d7a44103574d4cbfe3c15ae3940f0ffe75cd5e1e0afadb0a556b482b5dcb0d1a54b6e4070beb" 70 | }, 71 | { 72 | "salt": "salt", 73 | "password": "password", 74 | "N": 4, 75 | "r": 2, 76 | "p": 2, 77 | "dkLen": 48, 78 | "expected": "89d93e71c0cae21fb524624e6e0229ecae4fb727fb8e5b5f705aaed078aa455fba9e2186b6d5c7dcd7c9561affefd597" 79 | }, 80 | { 81 | "salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt", 82 | "password": "passwordPASSWORDpassword", 83 | "N": 2, 84 | "r": 1, 85 | "p": 1, 86 | "dkLen": 32, 87 | "expected": "2e40cbd0f2e5b348d11b25ce977f572c20bbb133b188c5b182f939e92f5581c1" 88 | }, 89 | { 90 | "salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt", 91 | "password": "passwordPASSWORDpassword", 92 | "N": 2, 93 | "r": 1, 94 | "p": 2, 95 | "dkLen": 32, 96 | "expected": "b8f439cd39d8c2db78fbc6846bbe4c7af559039af2a44140f4648333bd706a9f" 97 | }, 98 | { 99 | "salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt", 100 | "password": "passwordPASSWORDpassword", 101 | "N": 2, 102 | "r": 2, 103 | "p": 1, 104 | "dkLen": 32, 105 | "expected": "60ecb015fc3e8ee29c05253d3827639cee3163ba9e724e84675be7923101aba6" 106 | }, 107 | { 108 | "salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt", 109 | "password": "passwordPASSWORDpassword", 110 | "N": 4, 111 | "r": 1, 112 | "p": 1, 113 | "dkLen": 32, 114 | "expected": "0ca4071216a28c62c86e9b6499de4df73db413cb8f6af8e7210dbedb908340d3" 115 | }, 116 | { 117 | "salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt", 118 | "password": "passwordPASSWORDpassword", 119 | "N": 2, 120 | "r": 1, 121 | "p": 1, 122 | "dkLen": 48, 123 | "expected": "2e40cbd0f2e5b348d11b25ce977f572c20bbb133b188c5b182f939e92f5581c16f89084a1ceea4d5b52050498bd94ba5" 124 | }, 125 | { 126 | "salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt", 127 | "password": "passwordPASSWORDpassword", 128 | "N": 4, 129 | "r": 2, 130 | "p": 2, 131 | "dkLen": 48, 132 | "expected": "e5f5bce126455eec251b65667e0feb532b07ffcf56164c1b7e81e6cdd88a647cf679d16a7fe8d640de40028df832fd19" 133 | }, 134 | { 135 | "salt": "", 136 | "password": "", 137 | "N": 16, 138 | "r": 1, 139 | "p": 1, 140 | "dkLen": 64, 141 | "expected": "77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906" 142 | }, 143 | { 144 | "salt": "NaCl", // heh 145 | "password": "password", 146 | "N": 1024, 147 | "r": 8, 148 | "p": 16, 149 | "dkLen": 64, 150 | "expected": "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640" 151 | }, 152 | { 153 | "salt": "SodiumChloride", 154 | "password": "pleaseletmein", 155 | "N": 16384, 156 | "r": 8, 157 | "p": 1, 158 | "dkLen": 64, 159 | "expected": "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887" 160 | }, 161 | { 162 | "salt": "salt", 163 | "password": "Hellø", 164 | "N": 2, 165 | "r": 1, 166 | "p": 1, 167 | "dkLen": 64, 168 | "expected": "6837d88873b164bf5692e878fb0f20bd4a1cdc29f5f48a57e94a298984cbc661cb539e2a868498bee67a7a277d962d06ba1d45325eb1c756ff8f685bbacf585a" 169 | } 170 | 171 | 172 | 173 | ]; 174 | 175 | exports.defineAutoTests = function() { 176 | describe('cordova-plugin-scrypt', function () { 177 | 178 | it("should be defined", function() { 179 | expect(window.plugins.scrypt).toBeDefined(); 180 | }); 181 | 182 | it('derives the right keys from test vectors', function (done) { 183 | var count = 0; 184 | var fail = jasmine.createSpy('fail'); 185 | testCases.forEach(function (testCase) { 186 | window.plugins.scrypt( 187 | function(res){ 188 | expect(res).toEqual(testCase.expected); 189 | count++; 190 | if (count === testCases.length) done(); 191 | }, 192 | function (err) { 193 | fail(err); 194 | count++; 195 | expect(fail).not.toHaveBeenCalled(); 196 | if (count === testCases.length) done(); 197 | }, 198 | testCase.password, 199 | testCase.salt, 200 | testCase 201 | ); 202 | }); 203 | }); 204 | }); 205 | }; 206 | -------------------------------------------------------------------------------- /www/scrypt.js: -------------------------------------------------------------------------------- 1 | var scrypt = function(successCallback, errorCallback, message, salt, options) { 2 | if (typeof errorCallback != "function") { 3 | console.log("ScryptPlugin.scrypt failure: failure parameter not a function"); 4 | return; 5 | } 6 | 7 | if (typeof successCallback != "function") { 8 | console.log("ScryptPlugin.scrypt failure: success callback parameter must be a function"); 9 | return; 10 | } 11 | options = options || {}; 12 | cordova.exec(successCallback, errorCallback, "ScryptPlugin", "scrypt", [message, salt, options]); 13 | }; 14 | 15 | 16 | if(!window.plugins) { 17 | window.plugins = {}; 18 | } 19 | if (!window.plugins.scrypt) { 20 | window.plugins.scrypt = scrypt; 21 | } 22 | 23 | if (typeof module != 'undefined' && module.exports) { 24 | module.exports = scrypt; 25 | } --------------------------------------------------------------------------------