mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Start combining functionality.
This commit is contained in:
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Brian Pellin.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDroid.
|
||||||
|
*
|
||||||
|
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDroid is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.android.keepass.keepasslib;
|
||||||
|
|
||||||
|
import java.io.FilterOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.DataLengthException;
|
||||||
|
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||||
|
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||||||
|
|
||||||
|
public class BufferedBlockCipherOutputStream extends FilterOutputStream {
|
||||||
|
|
||||||
|
OutputStream mOS;
|
||||||
|
PaddedBufferedBlockCipher mCipher;
|
||||||
|
|
||||||
|
public BufferedBlockCipherOutputStream(OutputStream out) {
|
||||||
|
super(out);
|
||||||
|
mOS = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedBlockCipherOutputStream(OutputStream out, PaddedBufferedBlockCipher cipher) {
|
||||||
|
super(out);
|
||||||
|
mOS = out;
|
||||||
|
mCipher = cipher;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
byte[] block = new byte[2*mCipher.getBlockSize()];
|
||||||
|
int bytes;
|
||||||
|
try {
|
||||||
|
bytes = mCipher.doFinal(block, 0);
|
||||||
|
} catch (DataLengthException e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
throw new IOException("IllegalStateException.");
|
||||||
|
} catch (InvalidCipherTextException e) {
|
||||||
|
throw new IOException("InvalidCipherText.");
|
||||||
|
}
|
||||||
|
if ( bytes > 0 ) {
|
||||||
|
mOS.write(block, 0, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] buffer, int offset, int count) throws IOException {
|
||||||
|
int outputLen = mCipher.getUpdateOutputSize(count);
|
||||||
|
|
||||||
|
if ( outputLen > 0 ) {
|
||||||
|
byte[] block = new byte[outputLen];
|
||||||
|
int bytes = mCipher.processBytes(buffer, offset, count, block, 0);
|
||||||
|
if ( bytes > 0 ) {
|
||||||
|
mOS.write(block, 0, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] buffer) throws IOException {
|
||||||
|
int length = buffer.length;
|
||||||
|
int outputLen = mCipher.getUpdateOutputSize(length);
|
||||||
|
|
||||||
|
if ( outputLen > 0 ) {
|
||||||
|
byte[] block = new byte[outputLen];
|
||||||
|
int bytes = mCipher.processBytes(buffer, 0, length, block, 0);
|
||||||
|
|
||||||
|
if ( bytes > 0 ) {
|
||||||
|
mOS.write(block, 0, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int oneByte) throws IOException {
|
||||||
|
int outputLen = mCipher.getUpdateOutputSize(1);
|
||||||
|
|
||||||
|
if ( outputLen > 0 ) {
|
||||||
|
byte[] block = new byte[outputLen];
|
||||||
|
int bytes = mCipher.processByte((byte)oneByte, block, 0);
|
||||||
|
|
||||||
|
if ( bytes > 0 ) {
|
||||||
|
mOS.write(block, 0, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
51
src/com/android/keepass/keepasslib/NullOutputStream.java
Normal file
51
src/com/android/keepass/keepasslib/NullOutputStream.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Brian Pellin.
|
||||||
|
*
|
||||||
|
* This file is part of KeePassDroid.
|
||||||
|
*
|
||||||
|
* KeePassDroid is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* KeePassDroid is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with KeePassDroid. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.android.keepass.keepasslib;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class NullOutputStream extends OutputStream {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() throws IOException {
|
||||||
|
super.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] buffer, int offset, int count) throws IOException {
|
||||||
|
super.write(buffer, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] buffer) throws IOException {
|
||||||
|
super.write(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int oneByte) throws IOException {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -57,43 +57,20 @@ public class PwManagerOutput {
|
|||||||
mDebug = debug;
|
mDebug = debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public void close() throws PwManagerOutputException {
|
|
||||||
try {
|
|
||||||
mOS.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new PwManagerOutputException("Failed to close stream.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public byte[] getFinalKey(PwDbHeader header) throws PwManagerOutputException {
|
public byte[] getFinalKey(PwDbHeader header) throws PwManagerOutputException {
|
||||||
|
|
||||||
// Write checksum Checksum
|
|
||||||
MessageDigest md = null;
|
|
||||||
try {
|
try {
|
||||||
md = MessageDigest.getInstance("SHA-256");
|
return ImporterV3.makeFinalKey(header.masterSeed, header.masterSeed2, mPM.masterKey, mPM.numKeyEncRounds);
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (IOException e) {
|
||||||
assert true;
|
throw new PwManagerOutputException("Key creation failed: " + e.getMessage());
|
||||||
throw new PwManagerOutputException("SHA-256 not implemented here.");
|
|
||||||
}
|
}
|
||||||
NullOutputStream nos = new NullOutputStream();
|
|
||||||
DigestOutputStream dos = new DigestOutputStream(nos, md);
|
|
||||||
|
|
||||||
byte[] transformedMasterKey = ImporterV3.transformMasterKey(header.masterSeed2, mPM.masterKey, mPM.numKeyEncRounds);
|
|
||||||
try {
|
|
||||||
dos.write(header.masterSeed);
|
|
||||||
dos.write(transformedMasterKey);
|
|
||||||
} catch ( IOException e ) {
|
|
||||||
throw new PwManagerOutputException("Failed to build final key.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return md.digest();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getFinalKey2(PwDbHeader header) {
|
public byte[] getFinalKey2(PwDbHeader header) throws PwManagerOutputException {
|
||||||
return ImporterV3.makeFinalKey(header.masterSeed, header.masterSeed2, mPM.masterKey, mPM.numKeyEncRounds);
|
try {
|
||||||
|
return ImporterV3.makeFinalKey(header.masterSeed, header.masterSeed2, mPM.masterKey, mPM.numKeyEncRounds);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new PwManagerOutputException("Key creation failed: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void output() throws PwManagerOutputException, IOException {
|
public void output() throws PwManagerOutputException, IOException {
|
||||||
@@ -151,7 +128,7 @@ public class PwManagerOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cipher.init( Cipher.ENCRYPT_MODE, new SecretKeySpec(mPM.finalKey, "AES" ), new IvParameterSpec(header.encryptionIV) );
|
cipher.init( Cipher.ENCRYPT_MODE, new SecretKeySpec(finalKey, "AES" ), new IvParameterSpec(header.encryptionIV) );
|
||||||
CipherOutputStream cos = new CipherOutputStream(mOS, cipher);
|
CipherOutputStream cos = new CipherOutputStream(mOS, cipher);
|
||||||
outputPlanGroupAndEntries(cos);
|
outputPlanGroupAndEntries(cos);
|
||||||
cos.close();
|
cos.close();
|
||||||
|
|||||||
@@ -27,8 +27,10 @@ package org.phoneid.keepassj2me;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.DigestOutputStream;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
@@ -49,6 +51,8 @@ import org.phoneid.PhoneIDUtil;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.keepass.keepasslib.InvalidKeyFileException;
|
import com.android.keepass.keepasslib.InvalidKeyFileException;
|
||||||
|
import com.android.keepass.keepasslib.NullOutputStream;
|
||||||
|
import com.android.keepass.keepasslib.PwManagerOutput.PwManagerOutputException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a v3 database file.
|
* Load a v3 database file.
|
||||||
@@ -267,17 +271,23 @@ public class ImporterV3 {
|
|||||||
return newManager;
|
return newManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] makeFinalKey(byte[] masterSeed, byte[] masterSeed2, byte[] masterKey, int numRounds) {
|
public static byte[] makeFinalKey(byte[] masterSeed, byte[] masterSeed2, byte[] masterKey, int numRounds) throws IOException {
|
||||||
byte[] transformedMasterKey = transformMasterKey(masterSeed2, masterKey, numRounds );
|
|
||||||
|
|
||||||
// Hash the master password with the salt in the file
|
// Write checksum Checksum
|
||||||
SHA256Digest md = new SHA256Digest();
|
MessageDigest md = null;
|
||||||
md.update( masterSeed, 0, masterSeed.length );
|
try {
|
||||||
md.update( transformedMasterKey, 0, transformedMasterKey.length );
|
md = MessageDigest.getInstance("SHA-256");
|
||||||
byte[] finalKey = new byte[md.getDigestSize()];
|
} catch (NoSuchAlgorithmException e) {
|
||||||
md.doFinal(finalKey, 0);
|
throw new IOException("SHA-256 not implemented here.");
|
||||||
|
}
|
||||||
|
NullOutputStream nos = new NullOutputStream();
|
||||||
|
DigestOutputStream dos = new DigestOutputStream(nos, md);
|
||||||
|
|
||||||
return finalKey;
|
byte[] transformedMasterKey = ImporterV3.transformMasterKey(masterSeed2, masterKey, numRounds);
|
||||||
|
dos.write(masterSeed);
|
||||||
|
dos.write(transformedMasterKey);
|
||||||
|
|
||||||
|
return md.digest();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user