public static byte[] scryptDigest(byte[] input) { try { return SCrypt.scrypt(input, input, 1024, 1, 1, 32); } catch (Exception e) { return null; } }
public static byte[] computeSeedFromSaltAndPassword(String salt, String password) { try { byte[] seed = SCrypt.scrypt( CryptoUtils.decodeAscii(password), CryptoUtils.decodeAscii(salt), SCRYPT_PARAMS_N, SCRYPT_PARAMS_r, SCRYPT_PARAMS_p, SEED_LENGTH); return seed; } catch (GeneralSecurityException e) { throw new TechnicalException("Unable to salt password, using Scrypt library", e); } }
public static boolean doScrypt(byte[] databyte, byte[] target) throws GeneralSecurityException { // Initialize the nonce int[] nonce = new int[4]; nonce[3] = databyte[76]; nonce[2] = databyte[77]; nonce[1] = databyte[78]; nonce[0] = databyte[79]; int ns = 0; int cc; boolean found = false; // Loop over and increment nonce while (true) { // Set the bytes of the data to the nonce databyte[76] = (byte) (nonce[3] & 0xff); databyte[77] = (byte) (nonce[2] & 0xff); databyte[78] = (byte) (nonce[1] & 0xff); databyte[79] = (byte) (nonce[0] & 0xff); byte[] scrypted = (SCrypt.scryptJ( databyte, databyte, 1024, 1, 1, 32)); // Scrypt the data with proper params if (scrypted[31] == 0) { cc = 30; while ((cc > 0) && (scrypted[cc] == target[cc])) cc -= 1; if (((0x100 + scrypted[cc]) & 0xff) < ((0x100 + target[cc]) & 0xff)) { System.out.println(printByteArray(scrypted)); return true; } } incrementAtIndex(nonce, nonce.length - 1); // Otherwise increment the nonce ns += 1; if (ns > 0x4fff) { System.out.println("giving up on block\n"); return false; } } }
private byte[] decryptMnemonic(byte[] entropy, String normalizedPassphrase) throws GeneralSecurityException { byte[] salt = Arrays.copyOfRange(entropy, 32, 36); byte[] encrypted = Arrays.copyOf(entropy, 32); byte[] derived = SCrypt.scrypt(normalizedPassphrase.getBytes(Charsets.UTF_8), salt, 16384, 8, 8, 64); byte[] key = Arrays.copyOfRange(derived, 32, 64); SecretKeySpec keyspec = new SecretKeySpec(key, "AES"); DRMWorkaround.maybeDisableExportControls(); @SuppressLint("GetInstance") // ECB for 256 bits is enough, and is the same that BIP38 uses Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, keyspec); byte[] decrypted = cipher.doFinal(encrypted, 0, 32); for (int i = 0; i < 32; i++) decrypted[i] ^= derived[i]; byte[] hash = Sha256Hash.createDouble(decrypted).getBytes(); if (!Arrays.equals(Arrays.copyOf(hash, 4), salt)) throw new RuntimeException("Invalid checksum"); return decrypted; }