/**
* Copyright (C) 2012 cogroo <cogroo@cogroo.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cogroo.addon.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import org.cogroo.addon.LoggerImpl;
public class SecurityUtil {
private static final String UTF8 = "UTF-8";
protected static Logger LOG = LoggerImpl.getLogger(SecurityUtil.class.getCanonicalName());
/**
* Encrypt data using an key encrypted with a private key.
* @param privateKey the private key to decrypt the secret key
* @param encryptedSecretKey a encrypted secret key
* @param data the data to encrypt
* @return the encrypted data
* @throws InvalidKeyException one of the keys is invalid
*/
public byte[] encrypt(PrivateKey privateKey, byte[] encryptedSecretKey, String data) throws InvalidKeyException {
byte[] encryptedData = null;
try {
byte[] chave = privateKey.getEncoded();
// Decrypt secret symmetric key with private key
Cipher rsacf = Cipher.getInstance("RSA");
rsacf.init(Cipher.DECRYPT_MODE, privateKey);
byte[] secretKey = rsacf.doFinal(encryptedSecretKey);
encryptedData = encrypt(secretKey, data);
} catch (Exception e) {
LOG.log(Level.SEVERE, "Exception encrypting data", e);
}
return encryptedData;
}
private byte[] encrypt(byte[] secretKey, String data) throws InvalidKeyException {
byte[] encryptedData = null;
try {
// Encrypt data using the secret key
Cipher aescf = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivspec = new IvParameterSpec(new byte[16]);
aescf.init(Cipher.ENCRYPT_MODE,
new SecretKeySpec(secretKey, "AES"), ivspec);
encryptedData = aescf.doFinal(data.getBytes(UTF8));
} catch (Exception e) {
LOG.log(Level.SEVERE, "Exception encrypting data", e);
}
return encryptedData;
}
private byte[] decryptSecretKey(PrivateKey privatekey, byte[] encryptedSecretKey) {
byte[] result = null;
try {
Cipher rsacf = Cipher.getInstance("RSA");
rsacf.init(Cipher.DECRYPT_MODE, privatekey);
result = rsacf.doFinal(encryptedSecretKey);
} catch (Exception e) {
LOG.log(Level.SEVERE, "Error", e);
}
return result;
}
public byte[] decrypt(PrivateKey privateKey, byte[] encryptedSecretKey, byte[] encryptedText) {
byte[] text = null;
try {
byte[] secretKey = decryptSecretKey(privateKey, encryptedSecretKey);
text = decrypt(secretKey, encryptedText);
} catch (Exception e) {
LOG.log(Level.SEVERE, "Should not happen", e);
}
return text;
}
private byte[] decrypt(byte[] secretKey, byte[] encryptedText) {
byte[] text = null;
try {
Cipher aescf = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivspec = new IvParameterSpec(new byte[16]);
aescf.init(Cipher.DECRYPT_MODE,
new SecretKeySpec(secretKey, "AES"), ivspec);
text = aescf.doFinal(encryptedText);
} catch (Exception e) {
LOG.log(Level.SEVERE, "Should not happen", e);
}
return text;
}
private static final int RSAKEYSIZE = 1024;
public KeyPair genKeyPair() {
KeyPair kpr = null;
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(new RSAKeyGenParameterSpec(RSAKEYSIZE,
RSAKeyGenParameterSpec.F4));
kpr = kpg.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
LOG.log(Level.SEVERE, "Error generating key pair", e);
} catch (InvalidAlgorithmParameterException e) {
LOG.log(Level.SEVERE, "Error generating key pair", e);
}
return kpr;
}
public String encode(byte[] key) {
return StringUtils.newStringUtf8(Base64.encodeBase64(key, false));
}
public static String encodeURLSafe(String data) {
String ret = null;
try {
ret = URLEncoder.encode(data, UTF8);
} catch (Exception e) {
LOG.log(Level.SEVERE, "Should not happen", e);
}
return ret;
}
public String encodeURLSafe(byte[] key) {
String encKey = null;
try {
if(LOG.isLoggable(Level.FINE)) {
LOG.fine("encode 01: key " + Arrays.toString(key));
}
String value = encode(key);
if(LOG.isLoggable(Level.FINE)) {
LOG.fine("encode 02 value: " + value);
}
encKey = URLEncoder.encode(value, UTF8);
} catch (UnsupportedEncodingException e) {
LOG.log(Level.SEVERE, "Should not happen", e);
}
return encKey;
}
public byte[] decodeURLSafe(String encoded) {
byte[] bytes = null;
try {
bytes = Base64.decodeBase64(URLDecoder.decode(encoded, UTF8).getBytes(UTF8));
} catch (Exception e) {
LOG.log(Level.SEVERE, "Error decoding string: " + encoded, e);
}
return bytes;
}
/**
* Encrypt a string using SHA
* @param plaintext the original text
* @return resultant hash
*/
public synchronized String encrypt(String plaintext) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA");
md.update(plaintext.getBytes(UTF8));
} catch (Exception e) {
LOG.log(Level.SEVERE, "Should not happen!", e);
}
byte raw[] = md.digest();
return encode(raw);
}
}