DynamicKeyManager.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
* tags. See the COPYRIGHT.txt in the distribution for a full listing of
* individual contributors.
*
* All Waarp Project 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 3 of the License, or (at your
* option) any later version.
*
* Waarp 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
* Waarp . If not, see <http://www.gnu.org/licenses/>.
*/
package org.waarp.common.crypto;
import org.waarp.common.exception.CryptoException;
import org.waarp.common.file.FileUtils;
import org.waarp.common.utility.WaarpStringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
/**
* Can implements AES, ARCFOUR, Blowfish, DES, DESede, RC2, RC4<br>
* <br>
* The time ratio are: RC4,ARCFOUR=1; AES,RC2=1,5; DES=2; Blowfish,DESede=4<br>
* <b>AES is the best compromise in term of security and efficiency.</b>
*/
public class DynamicKeyManager extends KeyManager {
/**
* Manager of Dynamic Key
*/
private static final DynamicKeyManager manager = new DynamicKeyManager();
/**
* Extra information file extension
*/
private static final String INFEXTENSION = ".inf";
/**
* @return the current KeyManager
*/
public static KeyManager getInstance() {
return manager;
}
@Override
public final KeyObject createKeyObject() {
throw new InstantiationError(
"DynamicKeyManager does not implement this function");
}
@Override
public final List<String> initFromList(final List<String> keys) {
final LinkedList<String> wrong = new LinkedList<String>();
for (final String filename : keys) {
final File file = new File(filename);
if (file.canRead()) {
final String basename = file.getName();
final int lastpos = basename.lastIndexOf('.');
if (lastpos <= 0) {
wrong.add(filename);
continue;
}
final String firstname = basename.substring(0, lastpos);
final String extension = basename.substring(lastpos + 1);
int len = (int) file.length();
final byte[] key = new byte[len];
FileInputStream inputStream;
try {
inputStream = new FileInputStream(file);
} catch (final FileNotFoundException e) {
// should not be
wrong.add(filename);
continue;
}
int read = 1;
int offset = 0;
while (read > 0) {
try {
read = inputStream.read(key, offset, len);
} catch (final IOException e) {
wrong.add(filename);
read = -2;
break;
}
offset += read;
if (offset < len) {
len -= read;
} else {
break;
}
}
FileUtils.close(inputStream);
if (read < -1) {
// wrong
continue;
}
final String infFilename = filename + INFEXTENSION;
final File infFile = new File(infFilename);
inputStream = null;
try {
inputStream = new FileInputStream(infFile);
} catch (final FileNotFoundException e) {
// should not be
wrong.add(filename);
continue;
}
KeyObject keyObject;
try {
final int keySize = inputStream.read();
final String algo = readString(inputStream);
if (algo == null) {
wrong.add(filename);
continue;
}
final String instance = readString(inputStream);
if (instance == null) {
wrong.add(filename);
continue;
}
keyObject = new DynamicKeyObject(keySize, algo, instance, extension);
} catch (final IOException e1) {
wrong.add(filename);
continue;
} finally {
FileUtils.close(inputStream);
}
keyObject.setSecretKey(key);
setKey(firstname, keyObject);
} else {
wrong.add(filename);
}
}
isInitialized.set(true);
return wrong;
}
/**
* Specific functions to ease the process of reading the "inf" file
*
* @param inputStream
*
* @return the String that should be read
*/
private String readString(final FileInputStream inputStream) {
final int len;
try {
len = inputStream.read();
} catch (final IOException e1) {
return null;
}
final byte[] readbyte = new byte[len];
for (int i = 0; i < len; i++) {
try {
readbyte[i] = (byte) inputStream.read();
} catch (final IOException e) {
return null;
}
}
return new String(readbyte, WaarpStringUtils.UTF8);
}
@Override
public final void saveToFiles() throws CryptoException, IOException {
final Enumeration<String> names = keysConcurrentHashMap.keys();
while (names.hasMoreElements()) {
final String name = names.nextElement();
final KeyObject key = keysConcurrentHashMap.get(name);
key.saveSecretKey(new File(name + '.' + key.getFileExtension()));
final FileOutputStream outputStream = new FileOutputStream(
new File(name + '.' + key.getFileExtension() + INFEXTENSION));
try {
outputStream.write(key.getKeySize());
final String algo = key.getAlgorithm();
final String instance = key.getInstance();
outputStream.write(algo.length());
outputStream.write(algo.getBytes(WaarpStringUtils.UTF8));
outputStream.write(instance.length());
outputStream.write(instance.getBytes(WaarpStringUtils.UTF8));
} finally {
FileUtils.close(outputStream);
}
}
}
}