/**
* @(#) RSAUtil.java
*/
package edu.hust.util.security;
import java.math.*;
import java.io.*;
import java.security.*;
import java.security.spec.*;
import java.security.interfaces.*;
import javax.crypto.*;
/**
* EncryptException is an exception class from exception, handles any exceptions that
* may happen in the encryption/descryption.
*/
class EncryptException extends Exception {
/**
* Construct a new EncryptException
*/
public EncryptException() {
super();
}
/**
* Construct a new EncryptException
* @param msg exception message
*/
public EncryptException( String msg ) {
super( msg );
}
/**
* Construct a new EncryptException
* @ex exception
*/
public EncryptException( Throwable ex ) {
super( ex );
}
}
/**
* RSAUtil is a util class for implementing RSA algorithm,
* which needs bcprov-jdk1.4.jar being installed into CLASSPATH
* @author quickpoint
* @version 1.0 06/22/2005
*/
public class RSAUtil {
/**
* Generate key pair
* @return key pair
* @exception EncryptException throws when any exception happened in the generation
*/
public static KeyPair generateKeyPair()
throws EncryptException
{
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());
final int KEY_SIZE = 1024;
keyPairGenerator.initialize( KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyPairGenerator.genKeyPair();
return keyPair;
} catch ( Exception ex ) {
throw new EncryptException(ex);
}
}
/**
* Generate RSA public key
* @return RSA public key
* @exception when any exception happended in the generation.
*/
public static RSAPublicKey generateRSAPublicKey( byte[] modules, byte[] publicExponent )
throws EncryptException {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( new BigInteger( modules), new BigInteger( publicExponent));
return (RSAPublicKey) keyFac.generatePublic( pubKeySpec);
} catch ( Exception ex ) {
throw new EncryptException( ex );
}
}
/**
* Generate RSA private key
* @return private key
* @exception EncryptException throws when any exception happened in the generation
*/
public static RSAPrivateKey generateRSAPrivateKey( byte[] modules, byte[] privateExponent )
throws EncryptException {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec( new BigInteger( modules), new BigInteger( privateExponent ) );
return (RSAPrivateKey ) keyFac.generatePrivate( priKeySpec );
} catch ( Exception ex ) {
throw new EncryptException( ex );
}
}
/**
* Doing encryption with RSA
* @return cipher text
* @exception EncryptException throws when any exception happened in encryption
*/
public static byte[] encrypt(Key key, byte[] data) throws EncryptException {
try {
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, key);
int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(data.length);
int leavedSize = data.length % blockSize;
int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
byte[] raw = new byte[outputSize * blocksSize];
int i = 0;
while (data.length - i * blockSize > 0) {
if (data.length - i * blockSize > blockSize)
cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
else
cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
i++;
}
return raw;
} catch (Exception ex) {
throw new EncryptException(ex);
}
}
/**
* Doing decryption
* @return plain text
* @exception throws when any exception happened in the decryption.
*/
public static byte[] decrypt(Key key, byte[] raw) throws EncryptException {
try {
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE, key);
int blockSize = cipher.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
int j = 0;
while (raw.length - j * blockSize > 0) {
bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
j++;
}
return bout.toByteArray();
} catch (Exception ex) {
throw new EncryptException(ex);
}
}
/////////////////////////////////////////////////////////
// Text Handler
/////////////////////////////////////////////////////////
/**
* Store text
*
*/
public static boolean storeText( byte[] text, String fileName ) {
try {
OutputStream out = new FileOutputStream( fileName );
out.write( text );
out.flush();
out.close();
return true;
} catch ( FileNotFoundException fileNotFoundEx ) {
fileNotFoundEx.printStackTrace();
} catch ( IOException ioEx ) {
ioEx.printStackTrace();
}
return false;
}
///////////////////////////////////////////////////////////////
// Key handler
///////////////////////////////////////////////////////////////
/**
*
*/
public static boolean storeKey( Key key, String fileName ) {
try {
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream( fileName ));
out.writeObject( key );
out.close();
return true;
} catch ( FileNotFoundException fileNotFoundEx ) {
fileNotFoundEx.printStackTrace();
} catch ( IOException ioEx ) {
ioEx.printStackTrace();
}
return false;
}
/**
*
*/
public static RSAPublicKey loadPublicKey( String fileName ) {
RSAPublicKey rsaPubKey = null;
try {
ObjectInputStream in = new ObjectInputStream(
new FileInputStream( fileName ));
rsaPubKey = ( RSAPublicKey ) in.readObject();
} catch ( ClassNotFoundException classNotFoundEx ) {
classNotFoundEx.printStackTrace();
} catch ( FileNotFoundException fileNotFoundEx ) {
fileNotFoundEx.printStackTrace();
} catch ( IOException ioEx ) {
ioEx.printStackTrace();
}
return rsaPubKey;
}
/**
*
*/
public static RSAPrivateKey loadPrivateKey( String fileName ) {
RSAPrivateKey rsaPriKey = null;
try {
ObjectInputStream in = new ObjectInputStream(
new FileInputStream( fileName ));
rsaPriKey = ( RSAPrivateKey ) in.readObject();
} catch ( ClassNotFoundException classNotFoundEx ) {
classNotFoundEx.printStackTrace( );
} catch ( FileNotFoundException fileNotFoundEx ) {
fileNotFoundEx.printStackTrace( );
} catch ( IOException ioEx ) {
ioEx.printStackTrace();
}
return rsaPriKey;
}
// main, just for test
public static void main( String[] args ) {
String testFileName = "RSAUtil.java";
String cipherTextFileName = "cipherText.txt";
String plainTextFileName = "plainText.txt";
String pubKeyFileName = "pubkey.txt";
String priKeyFileName = "prikey.txt";
try {
System.out.println("load test file content...");
FileInputStream in = new FileInputStream( testFileName );
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] tmpBuf = new byte[1024];
int count = 0;
while( ( count = in.read(tmpBuf)) != -1 ) {
out.write(tmpBuf, 0, count );
tmpBuf = new byte[1024];
}
in.close();
out.close();
byte[] orgData = out.toByteArray();
System.out.println("generate key pair");
KeyPair keyPair = RSAUtil.generateKeyPair();
RSAPublicKey pubKey = (RSAPublicKey ) keyPair.getPublic();
RSAPrivateKey priKey = (RSAPrivateKey)keyPair.getPrivate();
/*
byte[] pubModBytes = pubKey.getModulus().toByteArray();
byte[] priModBytes = priKey.getModulus().toByteArray();
byte[] pubPubExponent = pubKey.getPublicExponent().toByteArray();
byte[] priPriExponent = priKey.getPrivateExponent().toByteArray();
RSAPublicKey recoverPubKey = RSAUtil.generateRSAPublicKey( pubModBytes, pubPubExponent );
RSAPrivateKey recoverPriKey = RSAUtil.generateRSAPrivateKey( priModBytes, priPriExponent );
*/
System.out.println( "encrypting...");
byte[] raw = RSAUtil.encrypt( pubKey, orgData);
System.out.println( "store key...");
storeKey(pubKey, pubKeyFileName );
storeKey(priKey, priKeyFileName );
System.out.println( "store cipher text...");
storeText( raw, cipherTextFileName );
////////////////////////////////////////
// decrypt
System.out.println( "load pri key" );
priKey = loadPrivateKey( priKeyFileName );
System.out.println( "decrypting...");
byte[] data = RSAUtil.decrypt( priKey , raw );
System.out.println( "store plain text...");
storeText( data, plainTextFileName );
} catch ( Exception ex ) {
ex.printStackTrace();
}
}
}