/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program 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
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.tools.cipher;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.nio.file.Path;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Level;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import com.rapidminer.tools.FileSystemService;
import com.rapidminer.tools.LogService;
/**
* The default {@link CipherKeyProvider} for RapidMiner Studio. It reads the Cipher key from a file
* called "cipher.key" which is stored within the RapidMiner user folder.
*
* @author Nils Woehler
* @since 6.2.0
*/
public class FileCipherKeyProvider implements CipherKeyProvider {
/** Default file name used to store the cipher. */
private static final String DEFAULTKEY_FILE_NAME = "cipher.key";
@Override
public SecretKey loadKey() throws KeyLoadingException {
// try to load key from file
File keyFile = new File(FileSystemService.getUserRapidMinerDir(), DEFAULTKEY_FILE_NAME);
try (FileInputStream fis = new FileInputStream(keyFile); ObjectInputStream in = new ObjectInputStream(fis)) {
int length = in.readInt();
byte[] rawKey = new byte[length];
int actualLength = in.read(rawKey);
if (length != actualLength) {
throw new IOException("Cannot read key file (unexpected length)");
}
return KeyGeneratorTool.makeKey(rawKey);
} catch (IOException e) {
// catch to log the problem, then throw again to indicate error
LogService.getRoot().log(Level.WARNING, "com.rapidminer.tools.cipher.KeyGeneratorTool.read_key_error",
e.getMessage());
throw new KeyLoadingException("Cannot retrieve key: " + e.getMessage());
}
}
@Override
public SecretKey createKey(int keyLength, String algorithm) throws KeyGenerationException {
KeyGenerator keyGenerator = null;
try {
keyGenerator = KeyGenerator.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new KeyGenerationException("Cannot generate key, generation algorithm not known.");
}
keyGenerator.init(keyLength, new SecureRandom());
// actual key generation
return keyGenerator.generateKey();
}
@Override
public void storeKey(Key key) throws KeyStoringException {
Path keyPath = FileSystemService.getUserRapidMinerDir().toPath().resolve(DEFAULTKEY_FILE_NAME);
try {
KeyGeneratorTool.storeKey(key.getEncoded(), keyPath);
} catch (IOException e) {
throw new KeyStoringException("Could not store new cipher key", e);
}
}
}