mirror of
https://github.com/m2049r/xmrwallet
synced 2025-04-06 13:06:37 +02:00
Fixes "Invalid Password" although password correct (#289)
* don't log warning * fix cn_slow_hash variant&prehash cn_slow_hash signature was changed in monero-core but the linker didn't notice - also added code to support wallets created with variant & prehash enabled
This commit is contained in:
parent
e109df34f0
commit
0cf5981eae
app/src/main
cpp
java/com/m2049r/xmrwallet/util
@ -697,16 +697,21 @@ Java_com_m2049r_xmrwallet_model_Wallet_isSynchronized(JNIEnv *env, jobject insta
|
|||||||
|
|
||||||
//void cn_slow_hash(const void *data, size_t length, char *hash); // from crypto/hash-ops.h
|
//void cn_slow_hash(const void *data, size_t length, char *hash); // from crypto/hash-ops.h
|
||||||
JNIEXPORT jbyteArray JNICALL
|
JNIEXPORT jbyteArray JNICALL
|
||||||
Java_com_m2049r_xmrwallet_util_KeyStoreHelper_cnSlowHash(JNIEnv *env, jobject clazz,
|
Java_com_m2049r_xmrwallet_util_KeyStoreHelper_slowHash(JNIEnv *env, jobject clazz,
|
||||||
jbyteArray data) {
|
jbyteArray data, jboolean broken) {
|
||||||
|
char hash[HASH_SIZE];
|
||||||
|
jsize size = env->GetArrayLength(data);
|
||||||
|
if (broken && (size < 200 /*sizeof(union hash_state)*/)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
jbyte *buffer = env->GetByteArrayElements(data, NULL);
|
jbyte *buffer = env->GetByteArrayElements(data, NULL);
|
||||||
jsize size = env->GetArrayLength(data);
|
if (broken) {
|
||||||
char hash[HASH_SIZE];
|
slow_hash_broken(buffer, hash);
|
||||||
cn_slow_hash(buffer, (size_t) size, hash);
|
} else {
|
||||||
|
slow_hash(buffer, (size_t) size, hash);
|
||||||
|
}
|
||||||
env->ReleaseByteArrayElements(data, buffer, JNI_ABORT); // do not update java byte[]
|
env->ReleaseByteArrayElements(data, buffer, JNI_ABORT); // do not update java byte[]
|
||||||
|
|
||||||
jbyteArray result = env->NewByteArray(HASH_SIZE);
|
jbyteArray result = env->NewByteArray(HASH_SIZE);
|
||||||
env->SetByteArrayRegion(result, 0, HASH_SIZE, (jbyte *) hash);
|
env->SetByteArrayRegion(result, 0, HASH_SIZE, (jbyte *) hash);
|
||||||
return result;
|
return result;
|
||||||
|
@ -60,7 +60,15 @@ enum {
|
|||||||
HASH_DATA_AREA = 136
|
HASH_DATA_AREA = 136
|
||||||
};
|
};
|
||||||
|
|
||||||
void cn_slow_hash(const void *data, size_t length, char *hash);
|
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed);
|
||||||
|
|
||||||
|
inline void slow_hash(const void *data, const size_t length, char *hash) {
|
||||||
|
cn_slow_hash(data, length, hash, 0 /* variant */, 0/*prehashed*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void slow_hash_broken(const void *data, char *hash) {
|
||||||
|
cn_slow_hash(data, 200 /*sizeof(union hash_state)*/, hash, 1 /* variant */, 1 /*prehashed*/);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ public class FingerprintHelper {
|
|||||||
KeyStoreHelper.loadWalletUserPass(context, wallet);
|
KeyStoreHelper.loadWalletUserPass(context, wallet);
|
||||||
return true;
|
return true;
|
||||||
} catch (KeyStoreHelper.BrokenPasswordStoreException ex) {
|
} catch (KeyStoreHelper.BrokenPasswordStoreException ex) {
|
||||||
Timber.w(ex);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,6 +302,16 @@ public class Helper {
|
|||||||
else return "";
|
else return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] hexToBytes(String hex) {
|
||||||
|
final int len = hex.length();
|
||||||
|
final byte[] data = new byte[len / 2];
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
|
||||||
|
+ Character.digit(hex.charAt(i + 1), 16));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
static public void setMoneroHome(Context context) {
|
static public void setMoneroHome(Context context) {
|
||||||
try {
|
try {
|
||||||
String home = getStorage(context, HOME_DIR).getAbsolutePath();
|
String home = getStorage(context, HOME_DIR).getAbsolutePath();
|
||||||
@ -351,6 +361,12 @@ public class Helper {
|
|||||||
return crazyPass;
|
return crazyPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// or maybe it is a broken CrAzYpass?
|
||||||
|
String brokenCrazyPass = KeyStoreHelper.getBrokenCrazyPass(context, password);
|
||||||
|
if (WalletManager.getInstance().verifyWalletPassword(walletPath, brokenCrazyPass, true)) {
|
||||||
|
return brokenCrazyPass;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import android.security.keystore.KeyGenParameterSpec;
|
|||||||
import android.security.keystore.KeyProperties;
|
import android.security.keystore.KeyProperties;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@ -61,17 +62,21 @@ public class KeyStoreHelper {
|
|||||||
System.loadLibrary("monerujo");
|
System.loadLibrary("monerujo");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static native byte[] cnSlowHash(byte[] data);
|
public static native byte[] slowHash(byte[] data, boolean broken);
|
||||||
|
|
||||||
static final private String RSA_ALIAS = "MonerujoRSA";
|
static final private String RSA_ALIAS = "MonerujoRSA";
|
||||||
|
|
||||||
public static String getCrazyPass(Context context, String password) {
|
private static String getCrazyPass(Context context, String password, boolean broken) {
|
||||||
byte[] data = password.getBytes(StandardCharsets.UTF_8);
|
byte[] data = password.getBytes(StandardCharsets.UTF_8);
|
||||||
byte[] sig = null;
|
byte[] sig = null;
|
||||||
try {
|
try {
|
||||||
KeyStoreHelper.createKeys(context, RSA_ALIAS);
|
KeyStoreHelper.createKeys(context, RSA_ALIAS);
|
||||||
sig = KeyStoreHelper.signData(RSA_ALIAS, data);
|
sig = KeyStoreHelper.signData(RSA_ALIAS, data);
|
||||||
return CrazyPassEncoder.encode(cnSlowHash(sig));
|
byte[] hash = slowHash(sig, broken);
|
||||||
|
if (hash == null) {
|
||||||
|
throw new IllegalStateException("Slow Hash is null!");
|
||||||
|
}
|
||||||
|
return CrazyPassEncoder.encode(hash);
|
||||||
} catch (NoSuchProviderException | NoSuchAlgorithmException |
|
} catch (NoSuchProviderException | NoSuchAlgorithmException |
|
||||||
InvalidAlgorithmParameterException | KeyStoreException |
|
InvalidAlgorithmParameterException | KeyStoreException |
|
||||||
InvalidKeyException | SignatureException ex) {
|
InvalidKeyException | SignatureException ex) {
|
||||||
@ -79,6 +84,18 @@ public class KeyStoreHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getCrazyPass(Context context, String password) {
|
||||||
|
return getCrazyPass(context, password, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBrokenCrazyPass(Context context, String password) {
|
||||||
|
// due to a link bug in the initial implementation, some crazypasses were built with
|
||||||
|
// prehash & variant == 1
|
||||||
|
// since there are wallets out there, we need to keep this here
|
||||||
|
return getCrazyPass(context, password, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean saveWalletUserPass(@NonNull Context context, String wallet, String password) {
|
public static boolean saveWalletUserPass(@NonNull Context context, String wallet, String password) {
|
||||||
String walletKeyAlias = SecurityConstants.WALLET_PASS_KEY_PREFIX + wallet;
|
String walletKeyAlias = SecurityConstants.WALLET_PASS_KEY_PREFIX + wallet;
|
||||||
byte[] data = password.getBytes(StandardCharsets.UTF_8);
|
byte[] data = password.getBytes(StandardCharsets.UTF_8);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user