/*
* Copyright (C) 2012, Katy Hilgenberg.
* Special acknowledgments to: Knowledge & Data Engineering Group, University of Kassel (http://www.kde.cs.uni-kassel.de).
* Contact: sdcf@cs.uni-kassel.de
*
* This file is part of the SDCFramework (Sensor Data Collection Framework) project.
*
* The SDCFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The SDCFramework 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SDCFramework. If not, see <http://www.gnu.org/licenses/>.
*/
package de.unikassel.android.sdcframework.util.facade;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
/**
* Utility class for encryption and checksums.
*
* @author Katy Hilgenberg
*
*/
public final class Encryption
{
/**
* private key file name
*/
public static final String PRIVATE_KEY_FILE = "private.key";
/**
* public key file name
*/
public static final String PUBLIC_KEY_FILE = "public.key";
/**
* The RSA key length
*/
private static final int RSA_KEY_LENGTH = 2048;
/**
* The RSA algorithm description
*/
private static final String RSA_ALGORITHM = "RSA";
/**
* The RSA transformation description for encryption
*/
private static final String RSA_ENCRYPTION = RSA_ALGORITHM
+ "/ECB/PKCS1Padding";
/**
* Method to create an MD5 hash for a given string
*
* @param text
* the string to create MD5 hash for
* @return the MD5 hash for the text
*/
public static final String md5( String text )
{
String hash = null;
try
{
MessageDigest messageDigest =
java.security.MessageDigest.getInstance( "MD5" );
messageDigest.update( text.getBytes() );
byte digest[] = messageDigest.digest();
StringBuffer hexString = new StringBuffer();
for ( int i = 0; i < digest.length; i++ )
{
String hexDigest = Integer.toHexString( 0xFF & digest[ i ] );
if ( hexDigest.length() < 2 )
hexString.append( '0' );
hexString.append( hexDigest );
}
hash = hexString.toString();
}
catch ( NoSuchAlgorithmException e )
{
e.printStackTrace();
}
return hash;
}
/**
* Method for RSA file encryption
*
* @param key
* the public key to use for encryption
* @param srcFile
* the source file to encrypt
* @param destFile
* the file to store encrypted data in
* @return true if successful, false otherwise
*/
public static final boolean encryptRSA( PublicKey key, File srcFile,
File destFile )
{
BufferedInputStream is = null;
BufferedOutputStream os = null;
boolean result = false;
try
{
Cipher cipher = Cipher.getInstance( RSA_ENCRYPTION );
cipher.init( Cipher.ENCRYPT_MODE, key );
is = new BufferedInputStream( new FileInputStream( srcFile ) );
os = new BufferedOutputStream( new FileOutputStream( destFile ) );
byte[] bytes = new byte[ RSA_KEY_LENGTH / 8 - 11 ];
int i = is.read( bytes );
while ( i != -1 )
{
byte[] encBytes = cipher.doFinal( bytes, 0, i );
os.write( encBytes );
i = is.read( bytes );
}
os.flush();
result = true;
}
catch ( Exception e )
{
e.printStackTrace();
}
finally
{
try
{
if ( is != null )
{
is.close();
}
if ( os != null )
{
os.close();
}
}
catch ( Exception e )
{}
}
return result;
}
/**
* Method for RSA file decryption
*
* @param key
* the private key to use for decryption
* @param srcFile
* the source file to decrypt
* @param destFile
* the file to store decrypted data in
* @return true if successful, false otherwise
*/
public static final boolean decryptRSA( PrivateKey key, File srcFile,
File destFile )
{
BufferedInputStream is = null;
BufferedOutputStream os = null;
boolean result = false;
try
{
Cipher cipher = Cipher.getInstance( RSA_ENCRYPTION );
cipher.init( Cipher.DECRYPT_MODE, key );
is = new BufferedInputStream( new FileInputStream( srcFile ) );
os = new BufferedOutputStream( new FileOutputStream( destFile ) );
byte[] bytes = new byte[ RSA_KEY_LENGTH / 8 ];
int i = is.read( bytes );
while ( i != -1 )
{
byte[] encBytes = cipher.doFinal( bytes, 0, i );
os.write( encBytes );
i = is.read( bytes );
}
os.flush();
result = true;
}
catch ( Exception e )
{
e.printStackTrace();
}
finally
{
try
{
if ( is != null )
{
is.close();
}
if ( os != null )
{
os.close();
}
}
catch ( Exception e )
{}
}
return result;
}
/**
* Method to create an RSA key pair of RSA_KEY_LENGTH bit length and save the
* key bytes to files.
*
* @return the genrated key pair
*/
public static final KeyPair createRSAKeyPair()
{
try
{
KeyPairGenerator generator = KeyPairGenerator.getInstance( RSA_ALGORITHM );
generator.initialize( RSA_KEY_LENGTH );
KeyPair keyPair = generator.genKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
saveRSAKeyToFile( PUBLIC_KEY_FILE, publicKey.getEncoded() );
saveRSAKeyToFile( PRIVATE_KEY_FILE, privateKey.getEncoded() );
return keyPair;
}
catch ( Exception e )
{
e.printStackTrace();
}
return null;
}
/**
* Method to store a public or a private RSA key bytes
*
* @param file
* the file to save the key into
* @param bytes
* the key bytes
* @throws IOException
*/
public static final void saveRSAKeyToFile( String file, byte[] bytes )
throws IOException
{
OutputStream os = new BufferedOutputStream( new FileOutputStream( file ) );
try
{
os.write( bytes );
}
finally
{
os.close();
}
}
/**
* Method to read a public key from file
*
* @param file
* the file to read the public key from
* @return the public key
*/
public static final PublicKey readPublicKeyFromFile( File file )
{
PublicKey key = null;
try
{
byte[] bytes = readRSAKeyFromFile( file );
key =
KeyFactory.getInstance( RSA_ALGORITHM ).generatePublic(
new X509EncodedKeySpec( bytes ) );
}
catch ( Exception e )
{
e.printStackTrace();
}
return key;
}
/**
* Method to read a public key from an input stream
*
* @param is
* the input stream to read from
* @return the public key
*/
public static final PublicKey readPublicKeyFromStream( InputStream is )
{
PublicKey key = null;
try
{
byte[] bytes = readRSAKeyFromStream( is );
key = KeyFactory.getInstance( RSA_ALGORITHM ).generatePublic(
new X509EncodedKeySpec( bytes ) );
}
catch ( Exception e )
{
e.printStackTrace();
}
return key;
}
/**
* Method to read a private key from file
*
* @param file
* the file to read the private key from
* @return the private key
*/
public static final PrivateKey readPrivateKeyFromFile( File file )
{
PrivateKey key = null;
try
{
byte[] bytes = readRSAKeyFromFile( file );
key =
KeyFactory.getInstance( RSA_ALGORITHM ).generatePrivate(
new PKCS8EncodedKeySpec( bytes ) );
}
catch ( Exception e )
{
e.printStackTrace();
}
return key;
}
/**
* Method to store a public or a private RSA key bytes
*
* @param file
* the file to read the public key from
* @return the key bytes
* @throws IOException
*/
private static final byte[] readRSAKeyFromFile( File file )
throws IOException
{
long length = file.length();
if ( length > 0 )
{
return readRSAKeyFromStream( new BufferedInputStream(
new FileInputStream( file ) ) );
}
return null;
}
/**
* Method to store a public or a private RSA key bytes
*
* @param is
* the input stream to read the public key from
* @return the key bytes
* @throws IOException
*/
public static final byte[] readRSAKeyFromStream( InputStream is )
throws IOException
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[ 1024 ];
try
{
int i = is.read( buffer );
while ( i != -1 )
{
os.write( buffer, 0, i );
i = is.read( buffer );
}
}
finally
{
is.close();
os.flush();
}
return os.toByteArray();
}
}