001: package com.quadcap.sql.file;
002:
003: /*
004: * Copyright 1999 by Stan Bailes and Quadcap Software.
005: *
006: **/
007:
008: import java.io.IOException;
009:
010: import java.nio.ByteBuffer;
011:
012: import com.quadcap.crypto.Digest;
013: import com.quadcap.crypto.Key;
014: import com.quadcap.crypto.KeyFactory;
015: import com.quadcap.crypto.SymmetricKey;
016:
017: /**
018: *
019: *
020: * @author Stan Bailes
021: */
022: public class EncryptedBlockStore extends BlockStore {
023: SymmetricKey key;
024: Key encrypt;
025: Key decrypt;
026: byte[] buf0;
027: ByteBuffer b0;
028:
029: /**
030: * Create a new EncryptedBlockStore object using the specified file and
031: * blocksize.
032: *
033: * @param file the underlying file.
034: * @param ra the randomly-accessible version of the file.
035: * @param blocksize the block size to use for accessing the file.
036: */
037: public EncryptedBlockStore() {
038: }
039:
040: static final int oHASH_PASSWD_start = BlockFile.oHASH_PASSWD_start;
041: static final int oHASH_PASSWD_len = BlockFile.oHASH_PASSWD_len;
042:
043: public void setKey(SymmetricKey key) throws IOException {
044: this .key = key;
045: this .encrypt = key.getEncryptionKey();
046: this .decrypt = key.getDecryptionKey();
047: this .buf0 = new byte[blockSize];
048: b0 = ByteBuffer.wrap(buf0);
049: byte[] digest = makeDigest(key.toString());
050: if (!isEncrypted()) {
051: synchronized (lock) {
052: buf0[0] = 0x0e; // 4c -> ec! Encrypted.
053: fra.write(0, buf0, 0, 1);
054: fra.write(oHASH_PASSWD_start, digest, 0, digest.length);
055: }
056: } else {
057: synchronized (lock) {
058: fra.read(oHASH_PASSWD_start, buf0, 0, oHASH_PASSWD_len);
059: for (int i = 0; i < digest.length; i++) {
060: if (digest[i] != buf0[i]) {
061: throw new IOException("Bad username/password");
062: }
063: }
064: }
065: }
066: }
067:
068: byte[] makeDigest(String s) {
069: Digest d = KeyFactory.createDigest("SHA1");
070: for (int i = 0; i < s.length(); i++) {
071: char c = s.charAt(i);
072: d.update((byte) ((c >> 8) & 0xff));
073: d.update((byte) (c & 0xff));
074: }
075: return d.digest();
076: }
077:
078: /**
079: * Read a block into a buffer. If the specified block is beyond the
080: * current end of file, then grow the file
081: *
082: * @param blockNum the number of the block to read.
083: * @param buf the buffer into which the data is read.
084: */
085: public void read(long blockNum, byte[] buf) throws IOException {
086: synchronized (lock) {
087: if (blockNum != 0 && decrypt != null) {
088: super .read(blockNum, buf0);
089: b0.rewind();
090: decrypt.f(b0, ByteBuffer.wrap(buf));
091: } else {
092: super .read(blockNum, buf);
093: }
094: }
095: }
096:
097: /**
098: * Write a block from a buffer into the file.
099: *
100: * @param blockNum the number of the block to write.
101: * @param buf the buffer from which the data is written.
102: * @exception IOException if an I/O error occurs.
103: */
104: public void write(long blockNum, byte[] buf) throws IOException {
105: synchronized (lock) {
106: if (blockNum != 0 && encrypt != null) {
107: b0.clear();
108: encrypt.f(ByteBuffer.wrap(buf), b0);
109: super.write(blockNum, buf0);
110: } else {
111: super.write(blockNum, buf);
112: }
113: }
114: }
115: }
|