public static String encrypt (byte[] seed, Date birth, String passphrase, ScryptDifficulty scryptDifficulty) throws ValidationException
{
if ( seed == null || (seed.length != 16 && seed.length != 32 && seed.length != 64) )
{
throw new ValidationException ("Seed must be 16, 32 or 64 bytes");
}
int weeks =
(int) ((birth.getTime () - new GregorianCalendar (2013, Calendar.JANUARY, 1).getTime ().getTime ()) / (7 * 24 * 60 * 60 * 1000L));
ExtendedKey key = ExtendedKey.create (seed);
byte raw[];
byte[] salt = new byte[9];
if ( seed.length == 16 )
{
raw = new byte[25];
System.arraycopy (encrypted16, 0, salt, 0, 3);
}
else if ( seed.length == 32 )
{
raw = new byte[41];
System.arraycopy (encrypted32, 0, salt, 0, 3);
}
else
{
raw = new byte[73];
System.arraycopy (encrypted64, 0, salt, 0, 3);
}
salt[2] += scryptDifficulty.ordinal ();
salt[3] = (byte) (weeks & 0xff);
salt[4] = (byte) ((weeks >>> 8) & 0xff);
System.arraycopy (Hash.hash (key.getMaster ().getPrivate ()), 0, salt, 5, 4);
System.arraycopy (salt, 0, raw, 0, 9);
int N = (1 << 14) << (scryptDifficulty.ordinal () * 2);
int r = scryptDifficulty == ScryptDifficulty.LOW ? 8 : 16;
int p = scryptDifficulty == ScryptDifficulty.LOW ? 8 : 16;
Mac mac;
try
{
mac = Mac.getInstance ("HmacSHA512", "BC");
SecretKey seedkey = new SecretKeySpec (salt, "HmacSHA512");
mac.init (seedkey);
byte[] preH = mac.doFinal (passphrase.getBytes ("UTF-8"));
byte[] strongH = SCrypt.generate (preH, preH, N, r, p, 64);
seedkey = new SecretKeySpec (passphrase.getBytes ("UTF-8"), "HmacSHA512");
mac.init (seedkey);
byte[] postH = mac.doFinal (salt);
byte[] H = SCrypt.generate (postH, strongH, 1 << 10, 1, 1, seed.length + 32);
byte[] X = Arrays.copyOf (H, seed.length);
for ( int i = 0; i < seed.length; ++i )
{
X[i] ^= seed[i];
}
SecretKeySpec keyspec = new SecretKeySpec (Arrays.copyOfRange (H, seed.length, seed.length + 32), "AES");
Cipher cipher = Cipher.getInstance ("AES/ECB/NoPadding", "BC");
cipher.init (Cipher.ENCRYPT_MODE, keyspec);
System.arraycopy (cipher.doFinal (X), 0, raw, 9, seed.length);
}
catch ( NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | UnsupportedEncodingException | NoSuchPaddingException
| IllegalBlockSizeException | BadPaddingException e )
{
throw new ValidationException (e);
}
return ByteUtils.toBase58WithChecksum (raw);
}