Start combining functionality.

This commit is contained in:
Brian Pellin
2009-05-03 21:41:06 -05:00
parent 1fd24e53fc
commit af7dab779a
4 changed files with 187 additions and 43 deletions

View File

@@ -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);
}
}
}
}

View 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 {
}
}

View File

@@ -57,43 +57,20 @@ public class PwManagerOutput {
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 {
// Write checksum Checksum
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
assert true;
throw new PwManagerOutputException("SHA-256 not implemented here.");
return ImporterV3.makeFinalKey(header.masterSeed, header.masterSeed2, mPM.masterKey, mPM.numKeyEncRounds);
} catch (IOException e) {
throw new PwManagerOutputException("Key creation failed: " + e.getMessage());
}
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) {
return ImporterV3.makeFinalKey(header.masterSeed, header.masterSeed2, mPM.masterKey, mPM.numKeyEncRounds);
public byte[] getFinalKey2(PwDbHeader header) throws PwManagerOutputException {
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 {
@@ -151,7 +128,7 @@ public class PwManagerOutput {
}
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);
outputPlanGroupAndEntries(cos);
cos.close();

View File

@@ -27,8 +27,10 @@ package org.phoneid.keepassj2me;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.DigestOutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
@@ -49,6 +51,8 @@ import org.phoneid.PhoneIDUtil;
import android.util.Log;
import com.android.keepass.keepasslib.InvalidKeyFileException;
import com.android.keepass.keepasslib.NullOutputStream;
import com.android.keepass.keepasslib.PwManagerOutput.PwManagerOutputException;
/**
* Load a v3 database file.
@@ -267,17 +271,23 @@ public class ImporterV3 {
return newManager;
}
public static byte[] makeFinalKey(byte[] masterSeed, byte[] masterSeed2, byte[] masterKey, int numRounds) {
byte[] transformedMasterKey = transformMasterKey(masterSeed2, masterKey, numRounds );
public static byte[] makeFinalKey(byte[] masterSeed, byte[] masterSeed2, byte[] masterKey, int numRounds) throws IOException {
// Hash the master password with the salt in the file
SHA256Digest md = new SHA256Digest();
md.update( masterSeed, 0, masterSeed.length );
md.update( transformedMasterKey, 0, transformedMasterKey.length );
byte[] finalKey = new byte[md.getDigestSize()];
md.doFinal(finalKey, 0);
return finalKey;
// Write checksum Checksum
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new IOException("SHA-256 not implemented here.");
}
NullOutputStream nos = new NullOutputStream();
DigestOutputStream dos = new DigestOutputStream(nos, md);
byte[] transformedMasterKey = ImporterV3.transformMasterKey(masterSeed2, masterKey, numRounds);
dos.write(masterSeed);
dos.write(transformedMasterKey);
return md.digest();
}
/**