use of com.keepassdroid.stream.HmacBlockInputStream in project KeePassDX by Kunzisoft.
the class ImporterV4 method openDatabase.
@Override
public PwDatabaseV4 openDatabase(InputStream inStream, String password, InputStream keyInputStream, UpdateStatus status, long roundsFix) throws IOException, InvalidDBException {
db = createDB();
PwDbHeaderV4 header = new PwDbHeaderV4(db);
db.binPool.clear();
PwDbHeaderV4.HeaderAndHash hh = header.loadFromFile(inStream);
version = header.version;
hashOfHeader = hh.hash;
pbHeader = hh.header;
db.setMasterKey(password, keyInputStream);
db.makeFinalKey(header.masterSeed, db.kdfParameters, roundsFix);
CipherEngine engine;
Cipher cipher;
try {
engine = CipherFactory.getInstance(db.dataCipher);
db.dataEngine = engine;
cipher = engine.getCipher(Cipher.DECRYPT_MODE, db.finalKey, header.encryptionIV);
} catch (NoSuchAlgorithmException e) {
throw new IOException("Invalid algorithm.");
} catch (NoSuchPaddingException e) {
throw new IOException("Invalid algorithm.");
} catch (InvalidKeyException e) {
throw new IOException("Invalid algorithm.");
} catch (InvalidAlgorithmParameterException e) {
throw new IOException("Invalid algorithm.");
}
InputStream isPlain;
if (version < PwDbHeaderV4.FILE_VERSION_32_4) {
InputStream decrypted = AttachCipherStream(inStream, cipher);
LEDataInputStream dataDecrypted = new LEDataInputStream(decrypted);
byte[] storedStartBytes = null;
try {
storedStartBytes = dataDecrypted.readBytes(32);
if (storedStartBytes == null || storedStartBytes.length != 32) {
throw new InvalidPasswordException();
}
} catch (IOException e) {
throw new InvalidPasswordException();
}
if (!Arrays.equals(storedStartBytes, header.streamStartBytes)) {
throw new InvalidPasswordException();
}
isPlain = new HashedBlockInputStream(dataDecrypted);
} else {
// KDBX 4
LEDataInputStream isData = new LEDataInputStream(inStream);
byte[] storedHash = isData.readBytes(32);
if (!Arrays.equals(storedHash, hashOfHeader)) {
throw new InvalidDBException();
}
byte[] hmacKey = db.hmacKey;
byte[] headerHmac = PwDbHeaderV4.computeHeaderHmac(pbHeader, hmacKey);
byte[] storedHmac = isData.readBytes(32);
if (storedHmac == null || storedHmac.length != 32) {
throw new InvalidDBException();
}
// Mac doesn't match
if (!Arrays.equals(headerHmac, storedHmac)) {
throw new InvalidDBException();
}
HmacBlockInputStream hmIs = new HmacBlockInputStream(isData, true, hmacKey);
isPlain = AttachCipherStream(hmIs, cipher);
}
InputStream isXml;
if (db.compressionAlgorithm == PwCompressionAlgorithm.Gzip) {
isXml = new GZIPInputStream(isPlain);
} else {
isXml = isPlain;
}
if (version >= header.FILE_VERSION_32_4) {
LoadInnerHeader(isXml, header);
}
if (header.innerRandomStreamKey == null) {
assert (false);
throw new IOException("Invalid stream key.");
}
randomStream = PwStreamCipherFactory.getInstance(header.innerRandomStream, header.innerRandomStreamKey);
if (randomStream == null) {
throw new ArcFourException();
}
ReadXmlStreamed(isXml);
return db;
}
Aggregations