All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.h2.security.SecureFileStore Maven / Gradle / Ivy
/*
* Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (https://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.security;
import org.h2.engine.Constants;
import org.h2.store.DataHandler;
import org.h2.store.FileStore;
import org.h2.util.Bits;
import org.h2.util.MathUtils;
/**
* A file store that encrypts all data before writing, and decrypts all data
* after reading. Areas that were never written to (for example after calling
* setLength to enlarge the file) are not encrypted (contains 0 bytes).
*/
public class SecureFileStore extends FileStore {
private byte[] key;
private final BlockCipher cipher;
private final BlockCipher cipherForInitVector;
private byte[] buffer = new byte[4];
private long pos;
private final byte[] bufferForInitVector;
private final int keyIterations;
public SecureFileStore(DataHandler handler, String name, String mode,
String cipher, byte[] key, int keyIterations) {
super(handler, name, mode);
this.key = key;
this.cipher = CipherFactory.getBlockCipher(cipher);
this.cipherForInitVector = CipherFactory.getBlockCipher(cipher);
this.keyIterations = keyIterations;
bufferForInitVector = new byte[Constants.FILE_BLOCK_SIZE];
}
@Override
protected byte[] generateSalt() {
return MathUtils.secureRandomBytes(Constants.FILE_BLOCK_SIZE);
}
@Override
protected void initKey(byte[] salt) {
key = SHA256.getHashWithSalt(key, salt);
for (int i = 0; i < keyIterations; i++) {
key = SHA256.getHash(key, true);
}
cipher.setKey(key);
key = SHA256.getHash(key, true);
cipherForInitVector.setKey(key);
}
@Override
protected void writeDirect(byte[] b, int off, int len) {
super.write(b, off, len);
pos += len;
}
@Override
public void write(byte[] b, int off, int len) {
if (buffer.length < b.length) {
buffer = new byte[len];
}
System.arraycopy(b, off, buffer, 0, len);
xorInitVector(buffer, 0, len, pos);
cipher.encrypt(buffer, 0, len);
super.write(buffer, 0, len);
pos += len;
}
@Override
public void readFullyDirect(byte[] b, int off, int len) {
super.readFully(b, off, len);
pos += len;
}
@Override
public void readFully(byte[] b, int off, int len) {
super.readFully(b, off, len);
for (int i = 0; i < len; i++) {
if (b[i] != 0) {
cipher.decrypt(b, off, len);
xorInitVector(b, off, len, pos);
break;
}
}
pos += len;
}
@Override
public void seek(long x) {
this.pos = x;
super.seek(x);
}
private void xorInitVector(byte[] b, int off, int len, long p) {
byte[] iv = bufferForInitVector;
while (len > 0) {
for (int i = 0; i < Constants.FILE_BLOCK_SIZE; i += 8) {
Bits.writeLong(iv, i, (p + i) >>> 3);
}
cipherForInitVector.encrypt(iv, 0, Constants.FILE_BLOCK_SIZE);
for (int i = 0; i < Constants.FILE_BLOCK_SIZE; i++) {
b[off + i] ^= iv[i];
}
p += Constants.FILE_BLOCK_SIZE;
off += Constants.FILE_BLOCK_SIZE;
len -= Constants.FILE_BLOCK_SIZE;
}
}
}