use of com.keepassdroid.stream.NullOutputStream in project KeePassDX by Kunzisoft.
the class CryptoUtil method hashGen.
public static byte[] hashGen(String transform, byte[] data, int offset, int count) {
MessageDigest hash;
try {
hash = MessageDigest.getInstance(transform);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
NullOutputStream nos = new NullOutputStream();
DigestOutputStream dos = new DigestOutputStream(nos, hash);
try {
dos.write(data, offset, count);
dos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return hash.digest();
}
use of com.keepassdroid.stream.NullOutputStream in project KeePassDX by Kunzisoft.
the class PwDbV3Output method outputHeader.
public PwDbHeaderV3 outputHeader(OutputStream os) throws PwDbOutputException {
// Build header
PwDbHeaderV3 header = new PwDbHeaderV3();
header.signature1 = PwDbHeader.PWM_DBSIG_1;
header.signature2 = PwDbHeaderV3.DBSIG_2;
header.flags = PwDbHeaderV3.FLAG_SHA2;
if (mPM.getEncAlgorithm() == PwEncryptionAlgorithm.Rjindal) {
header.flags |= PwDbHeaderV3.FLAG_RIJNDAEL;
} else if (mPM.getEncAlgorithm() == PwEncryptionAlgorithm.Twofish) {
header.flags |= PwDbHeaderV3.FLAG_TWOFISH;
} else {
throw new PwDbOutputException("Unsupported algorithm.");
}
header.version = PwDbHeaderV3.DBVER_DW;
header.numGroups = mPM.getGroups().size();
header.numEntries = mPM.entries.size();
header.numKeyEncRounds = mPM.getNumKeyEncRecords();
setIVs(header);
// Content checksum
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new PwDbOutputException("SHA-256 not implemented here.");
}
// Header checksum
MessageDigest headerDigest;
try {
headerDigest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new PwDbOutputException("SHA-256 not implemented here.");
}
NullOutputStream nos;
nos = new NullOutputStream();
DigestOutputStream headerDos = new DigestOutputStream(nos, headerDigest);
// Output header for the purpose of calculating the header checksum
PwDbHeaderOutputV3 pho = new PwDbHeaderOutputV3(header, headerDos);
try {
pho.outputStart();
pho.outputEnd();
headerDos.flush();
} catch (IOException e) {
throw new PwDbOutputException(e);
}
byte[] headerHash = headerDigest.digest();
headerHashBlock = getHeaderHashBuffer(headerHash);
// Output database for the purpose of calculating the content checksum
nos = new NullOutputStream();
DigestOutputStream dos = new DigestOutputStream(nos, md);
BufferedOutputStream bos = new BufferedOutputStream(dos);
try {
outputPlanGroupAndEntries(bos);
bos.flush();
bos.close();
} catch (IOException e) {
throw new PwDbOutputException("Failed to generate checksum.");
}
header.contentsHash = md.digest();
// Output header for real output, containing content hash
pho = new PwDbHeaderOutputV3(header, os);
try {
pho.outputStart();
dos.on(false);
pho.outputContentHash();
dos.on(true);
pho.outputEnd();
dos.flush();
} catch (IOException e) {
throw new PwDbOutputException(e);
}
return header;
}
use of com.keepassdroid.stream.NullOutputStream in project KeePassDX by Kunzisoft.
the class ImporterV3 method openDatabase.
public PwDatabaseV3 openDatabase(InputStream inStream, String password, InputStream kfIs, UpdateStatus status, long roundsFix) throws IOException, InvalidDBException {
PwDatabaseV3 newManager;
// Load entire file, most of it's encrypted.
int fileSize = inStream.available();
// Pad with a blocksize (Twofish uses 128 bits), since Android 4.3 tries to write more to the buffer
byte[] filebuf = new byte[fileSize + 16];
inStream.read(filebuf, 0, fileSize);
inStream.close();
// Parse header (unencrypted)
if (fileSize < PwDbHeaderV3.BUF_SIZE)
throw new IOException("File too short for header");
PwDbHeaderV3 hdr = new PwDbHeaderV3();
hdr.loadFromFile(filebuf, 0);
if ((hdr.signature1 != PwDbHeader.PWM_DBSIG_1) || (hdr.signature2 != PwDbHeaderV3.DBSIG_2)) {
throw new InvalidDBSignatureException();
}
if (!hdr.matchesVersion()) {
throw new InvalidDBVersionException();
}
status.updateMessage(R.string.creating_db_key);
newManager = createDB();
newManager.setMasterKey(password, kfIs);
// Select algorithm
if ((hdr.flags & PwDbHeaderV3.FLAG_RIJNDAEL) != 0) {
newManager.algorithm = PwEncryptionAlgorithm.Rjindal;
} else if ((hdr.flags & PwDbHeaderV3.FLAG_TWOFISH) != 0) {
newManager.algorithm = PwEncryptionAlgorithm.Twofish;
} else {
throw new InvalidAlgorithmException();
}
// Copy for testing
newManager.copyHeader(hdr);
newManager.numKeyEncRounds = hdr.numKeyEncRounds;
newManager.name = "KeePass Password Manager";
// Generate transformedMasterKey from masterKey
newManager.makeFinalKey(hdr.masterSeed, hdr.transformSeed, newManager.numKeyEncRounds);
status.updateMessage(R.string.decrypting_db);
// Initialize Rijndael algorithm
Cipher cipher;
try {
if (newManager.algorithm == PwEncryptionAlgorithm.Rjindal) {
cipher = CipherFactory.getInstance("AES/CBC/PKCS5Padding");
} else if (newManager.algorithm == PwEncryptionAlgorithm.Twofish) {
cipher = CipherFactory.getInstance("Twofish/CBC/PKCS7PADDING");
} else {
throw new IOException("Encryption algorithm is not supported");
}
} catch (NoSuchAlgorithmException e1) {
throw new IOException("No such algorithm");
} catch (NoSuchPaddingException e1) {
throw new IOException("No such pdading");
}
try {
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(newManager.finalKey, "AES"), new IvParameterSpec(hdr.encryptionIV));
} catch (InvalidKeyException e1) {
throw new IOException("Invalid key");
} catch (InvalidAlgorithmParameterException e1) {
throw new IOException("Invalid algorithm parameter.");
}
// Decrypt! The first bytes aren't encrypted (that's the header)
int encryptedPartSize;
try {
encryptedPartSize = cipher.doFinal(filebuf, PwDbHeaderV3.BUF_SIZE, fileSize - PwDbHeaderV3.BUF_SIZE, filebuf, PwDbHeaderV3.BUF_SIZE);
} catch (ShortBufferException e1) {
throw new IOException("Buffer too short");
} catch (IllegalBlockSizeException e1) {
throw new IOException("Invalid block size");
} catch (BadPaddingException e1) {
throw new InvalidPasswordException();
}
// Copy decrypted data for testing
newManager.copyEncrypted(filebuf, PwDbHeaderV3.BUF_SIZE, encryptedPartSize);
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new IOException("No SHA-256 algorithm");
}
NullOutputStream nos = new NullOutputStream();
DigestOutputStream dos = new DigestOutputStream(nos, md);
dos.write(filebuf, PwDbHeaderV3.BUF_SIZE, encryptedPartSize);
dos.close();
byte[] hash = md.digest();
if (!Arrays.equals(hash, hdr.contentsHash)) {
Log.w("KeePassDroid", "Database file did not decrypt correctly. (checksum code is broken)");
throw new InvalidPasswordException();
}
// Import all groups
int pos = PwDbHeaderV3.BUF_SIZE;
PwGroupV3 newGrp = new PwGroupV3();
for (int i = 0; i < hdr.numGroups; ) {
int fieldType = LEDataInputStream.readUShort(filebuf, pos);
pos += 2;
int fieldSize = LEDataInputStream.readInt(filebuf, pos);
pos += 4;
if (fieldType == 0xFFFF) {
// End-Group record. Save group and count it.
newGrp.populateBlankFields(newManager);
newManager.groups.add(newGrp);
newGrp = new PwGroupV3();
i++;
} else {
readGroupField(newManager, newGrp, fieldType, filebuf, pos);
}
pos += fieldSize;
}
// Import all entries
PwEntryV3 newEnt = new PwEntryV3();
for (int i = 0; i < hdr.numEntries; ) {
int fieldType = LEDataInputStream.readUShort(filebuf, pos);
int fieldSize = LEDataInputStream.readInt(filebuf, pos + 2);
if (fieldType == 0xFFFF) {
// End-Group record. Save group and count it.
newEnt.populateBlankFields(newManager);
newManager.entries.add(newEnt);
newEnt = new PwEntryV3();
i++;
} else {
readEntryField(newManager, newEnt, filebuf, pos);
}
pos += 2 + 4 + fieldSize;
}
newManager.constructTree(null);
return newManager;
}
use of com.keepassdroid.stream.NullOutputStream in project keepass2android by PhilippC.
the class ImporterV3 method openDatabase.
public PwDatabaseV3 openDatabase(InputStream inStream, String password, InputStream keyfileStream, UpdateStatus status) throws IOException, InvalidDBException {
PwDatabaseV3 newManager;
// Load entire file, most of it's encrypted.
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = inStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
int fileSize = buffer.size();
// Pad with a blocksize (Twofish uses 128 bits), since Android 4.3 tries to write more to the buffer
for (int i = 0; i < 16; i++) {
buffer.write(0);
}
inStream.close();
byte[] filebuf = buffer.toByteArray();
// Parse header (unencrypted)
if (fileSize < PwDbHeaderV3.BUF_SIZE)
throw new IOException("File too short for header: " + fileSize + "<" + PwDbHeaderV3.BUF_SIZE);
PwDbHeaderV3 hdr = new PwDbHeaderV3();
hdr.loadFromFile(filebuf, 0);
if ((hdr.signature1 != PwDbHeader.PWM_DBSIG_1) || (hdr.signature2 != PwDbHeaderV3.DBSIG_2)) {
throw new InvalidDBSignatureException();
}
if (!hdr.matchesVersion()) {
throw new InvalidDBVersionException();
}
newManager = createDB();
newManager.setMasterKey(password, keyfileStream);
// Select algorithm
if ((hdr.flags & PwDbHeaderV3.FLAG_RIJNDAEL) != 0) {
newManager.algorithm = PwEncryptionAlgorithm.Rjindal;
} else if ((hdr.flags & PwDbHeaderV3.FLAG_TWOFISH) != 0) {
newManager.algorithm = PwEncryptionAlgorithm.Twofish;
} else {
throw new InvalidAlgorithmException();
}
// Copy for testing
newManager.copyHeader(hdr);
newManager.numKeyEncRounds = hdr.numKeyEncRounds;
newManager.name = "KeePass Password Manager";
// Generate transformedMasterKey from masterKey
newManager.makeFinalKey(hdr.masterSeed, hdr.transformSeed, newManager.numKeyEncRounds);
// Initialize Rijndael algorithm
Cipher cipher;
try {
if (newManager.algorithm == PwEncryptionAlgorithm.Rjindal) {
cipher = CipherFactory.getInstance("AES/CBC/PKCS5Padding");
} else if (newManager.algorithm == PwEncryptionAlgorithm.Twofish) {
cipher = CipherFactory.getInstance("TWOFISH/CBC/PKCS7PADDING");
} else {
throw new IOException("Encryption algorithm is not supported");
}
} catch (NoSuchAlgorithmException e1) {
throw new IOException("No such algorithm");
} catch (NoSuchPaddingException e1) {
throw new IOException("No such pdading");
}
try {
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(newManager.finalKey, "AES"), new IvParameterSpec(hdr.encryptionIV));
} catch (InvalidKeyException e1) {
throw new IOException("Invalid key");
} catch (InvalidAlgorithmParameterException e1) {
throw new IOException("Invalid algorithm parameter.");
}
// Decrypt! The first bytes aren't encrypted (that's the header)
int encryptedPartSize;
try {
encryptedPartSize = cipher.doFinal(filebuf, PwDbHeaderV3.BUF_SIZE, fileSize - PwDbHeaderV3.BUF_SIZE, filebuf, PwDbHeaderV3.BUF_SIZE);
} catch (ShortBufferException e1) {
throw new IOException("Buffer too short");
} catch (IllegalBlockSizeException e1) {
throw new IOException("Invalid block size");
} catch (BadPaddingException e1) {
throw new InvalidPasswordException("Invalid key!");
}
// Copy decrypted data for testing
newManager.copyEncrypted(filebuf, PwDbHeaderV3.BUF_SIZE, encryptedPartSize);
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new IOException("No SHA-256 algorithm");
}
NullOutputStream nos = new NullOutputStream();
DigestOutputStream dos = new DigestOutputStream(nos, md);
dos.write(filebuf, PwDbHeaderV3.BUF_SIZE, encryptedPartSize);
dos.close();
byte[] hash = md.digest();
if (!Arrays.equals(hash, hdr.contentsHash)) {
Log.w("KeePassDroid", "Database file did not decrypt correctly. (checksum code is broken)");
throw new InvalidPasswordException("Invalid key!");
}
// Import all groups
int pos = PwDbHeaderV3.BUF_SIZE;
PwGroupV3 newGrp = new PwGroupV3();
for (int i = 0; i < hdr.numGroups; ) {
int fieldType = LEDataInputStream.readUShort(filebuf, pos);
pos += 2;
int fieldSize = LEDataInputStream.readInt(filebuf, pos);
pos += 4;
if (fieldType == 0xFFFF) {
// End-Group record. Save group and count it.
newGrp.populateBlankFields(newManager);
newManager.groups.add(newGrp);
newGrp = new PwGroupV3();
i++;
} else {
readGroupField(newManager, newGrp, fieldType, filebuf, pos);
}
pos += fieldSize;
}
// Import all entries
PwEntryV3 newEnt = new PwEntryV3();
for (int i = 0; i < hdr.numEntries; ) {
int fieldType = LEDataInputStream.readUShort(filebuf, pos);
int fieldSize = LEDataInputStream.readInt(filebuf, pos + 2);
if (fieldType == 0xFFFF) {
// End-Group record. Save group and count it.
newEnt.populateBlankFields(newManager);
newManager.entries.add(newEnt);
newEnt = new PwEntryV3();
i++;
} else {
readEntryField(newManager, newEnt, filebuf, pos);
}
pos += 2 + 4 + fieldSize;
}
newManager.constructTree(null);
return newManager;
}
use of com.keepassdroid.stream.NullOutputStream in project KeePassDX by Kunzisoft.
the class PwManagerOutputTest method testChecksum.
public void testChecksum() throws NoSuchAlgorithmException, IOException, PwDbOutputException {
// FileOutputStream fos = new FileOutputStream("/dev/null");
NullOutputStream nos = new NullOutputStream();
MessageDigest md = MessageDigest.getInstance("SHA-256");
DigestOutputStream dos = new DigestOutputStream(nos, md);
PwDbV3Output pos = new PwDbV3OutputDebug(mPM, dos, true);
pos.outputPlanGroupAndEntries(dos);
dos.close();
byte[] digest = md.digest();
assertTrue("No output", digest.length > 0);
assertArrayEquals("Hash of groups and entries failed.", mPM.dbHeader.contentsHash, digest);
}
Aggregations