Java Code Examples for com.lambdaworks.crypto.SCrypt#scrypt()

The following examples show how to use com.lambdaworks.crypto.SCrypt#scrypt() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: BIP38PrivateKey.java    From bcm-android with GNU General Public License v3.0 6 votes vote down vote up
private ECKey decryptNoEC(String normalizedPassphrase) {
    try {
        byte[] derived = SCrypt.scrypt(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), addressHash, 16384, 8, 8, 64);
        byte[] key = Arrays.copyOfRange(derived, 32, 64);
        SecretKeySpec keyspec = new SecretKeySpec(key, "AES");

        DRMWorkaround.maybeDisableExportControls();
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");

        cipher.init(Cipher.DECRYPT_MODE, keyspec);
        byte[] decrypted = cipher.doFinal(content, 0, 32);
        for (int i = 0; i < 32; i++)
            decrypted[i] ^= derived[i];
        return ECKey.fromPrivate(decrypted, compressed);
    } catch (GeneralSecurityException x) {
        throw new RuntimeException(x);
    }
}
 
Example 2
Source File: Bip38.java    From bitherj with Apache License 2.0 6 votes vote down vote up
/**
 * Perform BIP38 compatible password stretching on a password to derive the
 * BIP38 key material
 *
 * @throws InterruptedException
 */
public static byte[] bip38Stretch1(CharSequence passphrase, byte[] salt, int outputSize)
        throws InterruptedException {
    byte[] passwordBytes = null;
    byte[] derived;
    try {
        passwordBytes = convertToByteArray(passphrase);
        derived = SCrypt.scrypt(convertToByteArray(passphrase), salt, SCRYPT_N, SCRYPT_R, SCRYPT_P, outputSize
        );
        return derived;
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    } finally {
        // Zero the password bytes.
        if (passwordBytes != null) {
            java.util.Arrays.fill(passwordBytes, (byte) 0);
        }
    }
}
 
Example 3
Source File: KeyCrypterScrypt.java    From bitherj with Apache License 2.0 6 votes vote down vote up
@Override
public KeyParameter deriveKey(CharSequence password) throws KeyCrypterException {
    byte[] passwordBytes = null;
    try {
        passwordBytes = convertToByteArray(password);
        byte[] salt = new byte[0];
        if (mSalt != null) {
            salt = mSalt;
        } else {
            // Warn the user that they are not using a salt.
            // (Some early MultiBit wallets had a blank salt).
            log.warn("You are using a ScryptParameters with no salt. Your encryption may be vulnerable to a dictionary attack.");
        }

        byte[] keyBytes = SCrypt.scrypt(passwordBytes, salt, BITCOINJ_SCRYPT_N, BITCOINJ_SCRYPT_R, BITCOINJ_SCRYPT_P, KEY_LENGTH);
        return new KeyParameter(keyBytes);
    } catch (Exception e) {
        throw new KeyCrypterException("Could not generate key from password and salt.", e);
    } finally {
        // Zero the password bytes.
        if (passwordBytes != null) {
            java.util.Arrays.fill(passwordBytes, (byte) 0);
        }
    }
}
 
Example 4
Source File: BIP38PrivateKey.java    From GreenBits with GNU General Public License v3.0 6 votes vote down vote up
private ECKey decryptNoEC(String normalizedPassphrase) {
    try {
        byte[] derived = SCrypt.scrypt(normalizedPassphrase.getBytes(Charsets.UTF_8), addressHash, 16384, 8, 8, 64);
        byte[] key = Arrays.copyOfRange(derived, 32, 64);
        SecretKeySpec keyspec = new SecretKeySpec(key, "AES");

        DRMWorkaround.maybeDisableExportControls();
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");

        cipher.init(Cipher.DECRYPT_MODE, keyspec);
        byte[] decrypted = cipher.doFinal(content, 0, 32);
        for (int i = 0; i < 32; i++)
            decrypted[i] ^= derived[i];
        return ECKey.fromPrivate(decrypted, compressed);
    } catch (GeneralSecurityException x) {
        throw new RuntimeException(x);
    }
}
 
Example 5
Source File: BIP38PrivateKey.java    From green_android with GNU General Public License v3.0 6 votes vote down vote up
private ECKey decryptNoEC(String normalizedPassphrase) {
    try {
        byte[] derived = SCrypt.scrypt(normalizedPassphrase.getBytes(Charsets.UTF_8), addressHash, 16384, 8, 8, 64);
        byte[] key = Arrays.copyOfRange(derived, 32, 64);
        SecretKeySpec keyspec = new SecretKeySpec(key, "AES");

        DRMWorkaround.maybeDisableExportControls();
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");

        cipher.init(Cipher.DECRYPT_MODE, keyspec);
        byte[] decrypted = cipher.doFinal(content, 0, 32);
        for (int i = 0; i < 32; i++)
            decrypted[i] ^= derived[i];
        return ECKey.fromPrivate(decrypted, compressed);
    } catch (GeneralSecurityException x) {
        throw new RuntimeException(x);
    }
}
 
Example 6
Source File: SCryptCrypto.java    From token-core-android with Apache License 2.0 5 votes vote down vote up
@Override
public byte[] generateDerivedKey(byte[] password) {
  int dkLen = this.kdfparams.getDklen();
  int n = this.kdfparams.getN();
  int p = this.kdfparams.getP();
  int r = this.kdfparams.getR();
  byte[] salt = NumericUtil.hexToBytes(this.kdfparams.getSalt());
  try {
    return SCrypt.scrypt(password, salt, n, r, p, dkLen);
  } catch (GeneralSecurityException e) {
    throw new TokenException(Messages.SCRYPT_PARAMS_INVALID, e);
  }
}
 
Example 7
Source File: ScryptTest.java    From token-core-android with Apache License 2.0 5 votes vote down vote up
@Test
public void derive() throws GeneralSecurityException {
    for(String[] example : ScryptExample) {
        byte[] derivedKey = SCrypt.scrypt(example[4].getBytes(), NumericUtil.hexToBytes(example[0]),
            Integer.parseInt(example[2]), Integer.parseInt(example[1]), Integer.parseInt(example[3]), Integer.parseInt(example[6]));
        assertEquals(example[5], NumericUtil.bytesToHex(derivedKey));
    }
}
 
Example 8
Source File: KeyCrypterScrypt.java    From green_android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Generate AES key.
 *
 * This is a very slow operation compared to encrypt/ decrypt so it is normally worth caching the result.
 *
 * @param password    The password to use in key generation
 * @return            The KeyParameter containing the created AES key
 * @throws            KeyCrypterException
 */
@Override
public KeyParameter deriveKey(CharSequence password) throws KeyCrypterException {
    byte[] passwordBytes = null;
    try {
        passwordBytes = convertToByteArray(password);
        byte[] salt = new byte[0];
        if ( scryptParameters.getSalt() != null) {
            salt = scryptParameters.getSalt().toByteArray();
        } else {
            // Warn the user that they are not using a salt.
            // (Some early MultiBit wallets had a blank salt).
            log.warn("You are using a ScryptParameters with no salt. Your encryption may be vulnerable to a dictionary attack.");
        }

        final Stopwatch watch = Stopwatch.createStarted();
        byte[] keyBytes = SCrypt.scrypt(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH);
        watch.stop();
        log.info("Deriving key took {} for {} scrypt iterations.", watch, scryptParameters.getN());
        return new KeyParameter(keyBytes);
    } catch (Exception e) {
        throw new KeyCrypterException("Could not generate key from password and salt.", e);
    } finally {
        // Zero the password bytes.
        if (passwordBytes != null) {
            java.util.Arrays.fill(passwordBytes, (byte) 0);
        }
    }
}
 
Example 9
Source File: Wallet.java    From web3sdk with Apache License 2.0 5 votes vote down vote up
private static byte[] generateDerivedScryptKey(
        byte[] password, byte[] salt, int n, int r, int p, int dkLen) throws CipherException {
    try {
        return SCrypt.scrypt(password, salt, n, r, p, dkLen);
    } catch (GeneralSecurityException e) {
        throw new CipherException(e);
    }
}
 
Example 10
Source File: KeyCrypterScrypt.java    From GreenBits with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Generate AES key.
 *
 * This is a very slow operation compared to encrypt/ decrypt so it is normally worth caching the result.
 *
 * @param password    The password to use in key generation
 * @return            The KeyParameter containing the created AES key
 * @throws            KeyCrypterException
 */
@Override
public KeyParameter deriveKey(CharSequence password) throws KeyCrypterException {
    byte[] passwordBytes = null;
    try {
        passwordBytes = convertToByteArray(password);
        byte[] salt = new byte[0];
        if ( scryptParameters.getSalt() != null) {
            salt = scryptParameters.getSalt().toByteArray();
        } else {
            // Warn the user that they are not using a salt.
            // (Some early MultiBit wallets had a blank salt).
            log.warn("You are using a ScryptParameters with no salt. Your encryption may be vulnerable to a dictionary attack.");
        }

        final Stopwatch watch = Stopwatch.createStarted();
        byte[] keyBytes = SCrypt.scrypt(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH);
        watch.stop();
        log.info("Deriving key took {} for {} scrypt iterations.", watch, scryptParameters.getN());
        return new KeyParameter(keyBytes);
    } catch (Exception e) {
        throw new KeyCrypterException("Could not generate key from password and salt.", e);
    } finally {
        // Zero the password bytes.
        if (passwordBytes != null) {
            java.util.Arrays.fill(passwordBytes, (byte) 0);
        }
    }
}
 
Example 11
Source File: Scrypt.java    From neb.java with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Override
public CryptoJSON encrypt(byte[] data, byte[] passphrase) throws Exception {
    byte[] salt = Utils.RandomBytes(CryptoJSON.ScryptDKLen);
    byte[] derivedKey = SCrypt.scrypt(passphrase, salt, CryptoJSON.StandardScryptN, CryptoJSON.StandardScryptR, CryptoJSON.StandardScryptP, CryptoJSON.ScryptDKLen);

    byte[] encryptKey = ByteUtils.SubBytes(derivedKey, 0, 16);
    byte[] iv = Utils.RandomBytes(16);
    SecretKeySpec key = new SecretKeySpec(encryptKey, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(iv);

    // https://stackoverflow.com/questions/31049685/aes-ctr-double-encryption-reverses-the-ciphertext-to-plaintext

    javax.crypto.Cipher AesCipher = javax.crypto.Cipher.getInstance("AES/CTR/NoPadding");
    AesCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, key, ivSpec);
    byte[] cipherText = AesCipher.doFinal(data);

    byte[] macDerivedKey = ByteUtils.SubBytes(derivedKey, 16, 16);
    byte[] mac = Hash.Sha3256(macDerivedKey, cipherText, iv, CryptoJSON.CIPHERNAME.getBytes());

    CryptoJSON.CipherParams cipherParams = new CryptoJSON.CipherParams();
    cipherParams.setIv(ByteUtils.HexToString(iv));

    CryptoJSON.ScryptParams scryptParams =  new CryptoJSON.ScryptParams();
    scryptParams.setN(CryptoJSON.StandardScryptN);
    scryptParams.setR(CryptoJSON.StandardScryptR);
    scryptParams.setP(CryptoJSON.StandardScryptP);
    scryptParams.setDklen(CryptoJSON.ScryptDKLen);
    scryptParams.setSalt(ByteUtils.HexToString(salt));

    CryptoJSON cryptoJSON = new CryptoJSON();
    cryptoJSON.setCipher(CryptoJSON.CIPHERNAME);
    cryptoJSON.setCiphertext(ByteUtils.HexToString(cipherText));
    cryptoJSON.setCipherparams(cipherParams);
    cryptoJSON.setKdf(CryptoJSON.ScryptKDF);
    cryptoJSON.setKdfparams(scryptParams);
    cryptoJSON.setMac(ByteUtils.HexToString(mac));
    cryptoJSON.setMachash(CryptoJSON.MACHASH);

    return cryptoJSON;
}
 
Example 12
Source File: KeyCrypterScrypt.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Generate AES key.
 * <p>
 * This is a very slow operation compared to encrypt/ decrypt so it is normally worth caching the result.
 *
 * @param password The password to use in key generation
 * @return The KeyParameter containing the created AES key
 * @throws KeyCrypterException
 */
@Override
public KeyParameter deriveKey(CharSequence password) throws KeyCrypterException {
    byte[] passwordBytes = null;
    try {
        passwordBytes = convertToByteArray(password);
        byte[] salt = new byte[0];
        if (scryptParameters.getSalt() != null) {
            salt = scryptParameters.getSalt().toByteArray();
        } else {
            // Warn the user that they are not using a salt.
            // (Some early MultiBit wallets had a blank salt).
            log.warn("You are using a ScryptParameters with no salt. Your encryption may be vulnerable to a dictionary attack.");
        }

        final Stopwatch watch = Stopwatch.createStarted();
        byte[] keyBytes = SCrypt.scrypt(passwordBytes, salt, (int) scryptParameters.getN(), scryptParameters.getR(), scryptParameters.getP(), KEY_LENGTH);
        watch.stop();
        log.info("Deriving key took {} for {} scrypt iterations.", watch, scryptParameters.getN());
        return new KeyParameter(keyBytes);
    } catch (Exception e) {
        throw new KeyCrypterException("Could not generate key from password and salt.", e);
    } finally {
        // Zero the password bytes.
        if (passwordBytes != null) {
            java.util.Arrays.fill(passwordBytes, (byte) 0);
        }
    }
}
 
Example 13
Source File: PasswordCrypt.java    From snowblossom with Apache License 2.0 4 votes vote down vote up
/**
 * Get the key bytes based on a password using the params in EncryptedFile.
 * Cache the result so we can decrypt/encrypt multiple files with the same
 * password quickly
 */
protected static ByteString getScryptKey(String pass, EncryptedFile params, int key_len)
{
  String param_token = String.format("%s.%d.%d.%d.%d", pass, params.getScryptCpuCost(),
    params.getScryptMemoryCost(),
    params.getScryptParallelizationCost(),
    key_len);

  synchronized(scrypt_params_to_key_map)
  {
    if (scrypt_params_to_key_map.containsKey(param_token))
    {
      return scrypt_params_to_key_map.get(param_token);
    }
  }

  try
  {
    long t1 = System.currentTimeMillis();
    byte[] key = SCrypt.scrypt(pass.getBytes(), SCRYPT_SALT.getBytes(),
        params.getScryptCpuCost(),
        params.getScryptMemoryCost(),
        params.getScryptParallelizationCost(),
        key_len);
    long t2 = System.currentTimeMillis();

    logger.log(Level.FINE, "Scrypt gen took: " + (t2 - t1) + " ms");

    ByteString key_bs = ByteString.copyFrom(key);

    synchronized(scrypt_params_to_key_map)
    {
      scrypt_params_to_key_map.put(param_token, key_bs);
    }

    return key_bs;

  }
  catch(java.security.GeneralSecurityException e)
  {
    throw new RuntimeException(e);
  }
}
 
Example 14
Source File: Scrypt.java    From neb.java with GNU Lesser General Public License v3.0 4 votes vote down vote up
@Override
public byte[] decrypt(CryptoJSON cryptoJSON, byte[] passphrase) throws Exception {
    if (!CryptoJSON.CIPHERNAME.equalsIgnoreCase(cryptoJSON.getCipher())) {
        throw new Exception("invalid cipher");
    }

    if (!CryptoJSON.ScryptKDF.equalsIgnoreCase(cryptoJSON.getKdf())) {
        throw new Exception("kdf not support");
    }

    byte[] mac = ByteUtils.HexToBytes(cryptoJSON.getMac());
    byte[] iv = ByteUtils.HexToBytes(cryptoJSON.getCipherparams().getIv());
    byte[] cipherText = ByteUtils.HexToBytes(cryptoJSON.getCiphertext());
    byte[] salt = ByteUtils.HexToBytes(cryptoJSON.getKdfparams().getSalt());

    int dklen = cryptoJSON.getKdfparams().getDklen();
    int n = cryptoJSON.getKdfparams().getN();
    int r = cryptoJSON.getKdfparams().getR();
    int p = cryptoJSON.getKdfparams().getP();

    byte[] derivedKey = SCrypt.scrypt(passphrase, salt, n, r, p, dklen);
    byte[] macDerivedKey = ByteUtils.SubBytes(derivedKey, 16, 16);
    byte[] calMac;
    if(cryptoJSON.getVersion() == 4) {
        calMac = Hash.Sha3256(macDerivedKey, cipherText, iv, cryptoJSON.getCipher().getBytes());
    } else {
        calMac = Hash.Sha3256(macDerivedKey, cipherText);
    }

    if (!ByteUtils.Equal(mac, calMac)) {
        throw new Exception("could not decrypt key with given passphrase");
    }

    byte[] encryptKey = ByteUtils.SubBytes(derivedKey, 0, 16);
    SecretKeySpec key = new SecretKeySpec(encryptKey, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(iv);

    javax.crypto.Cipher AesCipher = javax.crypto.Cipher.getInstance("AES/CTR/NoPadding");
    AesCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, key, ivSpec);
    byte[] result = AesCipher.doFinal(cipherText);
    return result;
}
 
Example 15
Source File: BIP38PrivateKey.java    From green_android with GNU General Public License v3.0 4 votes vote down vote up
private ECKey decryptEC(String normalizedPassphrase) {
    try {
        byte[] ownerEntropy = Arrays.copyOfRange(content, 0, 8);
        byte[] ownerSalt = hasLotAndSequence ? Arrays.copyOfRange(ownerEntropy, 0, 4) : ownerEntropy;

        byte[] passFactorBytes = SCrypt.scrypt(normalizedPassphrase.getBytes(Charsets.UTF_8), ownerSalt, 16384, 8, 8, 32);
        if (hasLotAndSequence) {
            byte[] hashBytes = Bytes.concat(passFactorBytes, ownerEntropy);
            checkState(hashBytes.length == 40);
            passFactorBytes = Sha256Hash.hashTwice(hashBytes);
        }
        BigInteger passFactor = new BigInteger(1, passFactorBytes);
        ECKey k = ECKey.fromPrivate(passFactor, true);

        byte[] salt = Bytes.concat(addressHash, ownerEntropy);
        checkState(salt.length == 12);
        byte[] derived = SCrypt.scrypt(k.getPubKey(), salt, 1024, 1, 1, 64);
        byte[] aeskey = Arrays.copyOfRange(derived, 32, 64);

        SecretKeySpec keyspec = new SecretKeySpec(aeskey, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, keyspec);

        byte[] encrypted2 = Arrays.copyOfRange(content, 16, 32);
        byte[] decrypted2 = cipher.doFinal(encrypted2);
        checkState(decrypted2.length == 16);
        for (int i = 0; i < 16; i++)
            decrypted2[i] ^= derived[i + 16];

        byte[] encrypted1 = Bytes.concat(Arrays.copyOfRange(content, 8, 16), Arrays.copyOfRange(decrypted2, 0, 8));
        byte[] decrypted1 = cipher.doFinal(encrypted1);
        checkState(decrypted1.length == 16);
        for (int i = 0; i < 16; i++)
            decrypted1[i] ^= derived[i];

        byte[] seed = Bytes.concat(decrypted1, Arrays.copyOfRange(decrypted2, 8, 16));
        checkState(seed.length == 24);
        BigInteger seedFactor = new BigInteger(1, Sha256Hash.hashTwice(seed));
        checkState(passFactor.signum() >= 0);
        checkState(seedFactor.signum() >= 0);
        BigInteger priv = passFactor.multiply(seedFactor).mod(ECKey.CURVE.getN());

        return ECKey.fromPrivate(priv, compressed);
    } catch (GeneralSecurityException x) {
        throw new RuntimeException(x);
    }
}
 
Example 16
Source File: BIP38PrivateKey.java    From GreenBits with GNU General Public License v3.0 4 votes vote down vote up
private ECKey decryptEC(String normalizedPassphrase) {
    try {
        byte[] ownerEntropy = Arrays.copyOfRange(content, 0, 8);
        byte[] ownerSalt = hasLotAndSequence ? Arrays.copyOfRange(ownerEntropy, 0, 4) : ownerEntropy;

        byte[] passFactorBytes = SCrypt.scrypt(normalizedPassphrase.getBytes(Charsets.UTF_8), ownerSalt, 16384, 8, 8, 32);
        if (hasLotAndSequence) {
            byte[] hashBytes = Bytes.concat(passFactorBytes, ownerEntropy);
            checkState(hashBytes.length == 40);
            passFactorBytes = Sha256Hash.hashTwice(hashBytes);
        }
        BigInteger passFactor = new BigInteger(1, passFactorBytes);
        ECKey k = ECKey.fromPrivate(passFactor, true);

        byte[] salt = Bytes.concat(addressHash, ownerEntropy);
        checkState(salt.length == 12);
        byte[] derived = SCrypt.scrypt(k.getPubKey(), salt, 1024, 1, 1, 64);
        byte[] aeskey = Arrays.copyOfRange(derived, 32, 64);

        SecretKeySpec keyspec = new SecretKeySpec(aeskey, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, keyspec);

        byte[] encrypted2 = Arrays.copyOfRange(content, 16, 32);
        byte[] decrypted2 = cipher.doFinal(encrypted2);
        checkState(decrypted2.length == 16);
        for (int i = 0; i < 16; i++)
            decrypted2[i] ^= derived[i + 16];

        byte[] encrypted1 = Bytes.concat(Arrays.copyOfRange(content, 8, 16), Arrays.copyOfRange(decrypted2, 0, 8));
        byte[] decrypted1 = cipher.doFinal(encrypted1);
        checkState(decrypted1.length == 16);
        for (int i = 0; i < 16; i++)
            decrypted1[i] ^= derived[i];

        byte[] seed = Bytes.concat(decrypted1, Arrays.copyOfRange(decrypted2, 8, 16));
        checkState(seed.length == 24);
        BigInteger seedFactor = new BigInteger(1, Sha256Hash.hashTwice(seed));
        checkState(passFactor.signum() >= 0);
        checkState(seedFactor.signum() >= 0);
        BigInteger priv = passFactor.multiply(seedFactor).mod(ECKey.CURVE.getN());

        return ECKey.fromPrivate(priv, compressed);
    } catch (GeneralSecurityException x) {
        throw new RuntimeException(x);
    }
}
 
Example 17
Source File: BIP38PrivateKey.java    From bcm-android with GNU General Public License v3.0 4 votes vote down vote up
private ECKey decryptEC(String normalizedPassphrase) {
    try {
        byte[] ownerEntropy = Arrays.copyOfRange(content, 0, 8);
        byte[] ownerSalt = hasLotAndSequence ? Arrays.copyOfRange(ownerEntropy, 0, 4) : ownerEntropy;

        byte[] passFactorBytes = SCrypt.scrypt(normalizedPassphrase.getBytes(StandardCharsets.UTF_8), ownerSalt, 16384, 8, 8, 32);
        if (hasLotAndSequence) {
            byte[] hashBytes = Bytes.concat(passFactorBytes, ownerEntropy);
            checkState(hashBytes.length == 40);
            passFactorBytes = Sha256Hash.hashTwice(hashBytes);
        }
        BigInteger passFactor = new BigInteger(1, passFactorBytes);
        ECKey k = ECKey.fromPrivate(passFactor, true);

        byte[] salt = Bytes.concat(addressHash, ownerEntropy);
        checkState(salt.length == 12);
        byte[] derived = SCrypt.scrypt(k.getPubKey(), salt, 1024, 1, 1, 64);
        byte[] aeskey = Arrays.copyOfRange(derived, 32, 64);

        SecretKeySpec keyspec = new SecretKeySpec(aeskey, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, keyspec);

        byte[] encrypted2 = Arrays.copyOfRange(content, 16, 32);
        byte[] decrypted2 = cipher.doFinal(encrypted2);
        checkState(decrypted2.length == 16);
        for (int i = 0; i < 16; i++)
            decrypted2[i] ^= derived[i + 16];

        byte[] encrypted1 = Bytes.concat(Arrays.copyOfRange(content, 8, 16), Arrays.copyOfRange(decrypted2, 0, 8));
        byte[] decrypted1 = cipher.doFinal(encrypted1);
        checkState(decrypted1.length == 16);
        for (int i = 0; i < 16; i++)
            decrypted1[i] ^= derived[i];

        byte[] seed = Bytes.concat(decrypted1, Arrays.copyOfRange(decrypted2, 8, 16));
        checkState(seed.length == 24);
        BigInteger seedFactor = new BigInteger(1, Sha256Hash.hashTwice(seed));
        checkState(passFactor.signum() >= 0);
        checkState(seedFactor.signum() >= 0);
        BigInteger priv = passFactor.multiply(seedFactor).mod(ECKey.CURVE.getN());

        return ECKey.fromPrivate(priv, compressed);
    } catch (GeneralSecurityException x) {
        throw new RuntimeException(x);
    }
}