package lucee.commons.digest;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import lucee.runtime.coder.CoderException;
public class RSA {
private static final int KEY_SIZE = 1024;
public static String toString(PrivateKey privateKey) {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
return toString(pkcs8EncodedKeySpec.getEncoded());
}
public static String toString(PublicKey publicKey) {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
return toString(x509EncodedKeySpec.getEncoded());
}
public static PrivateKey toPrivateKey(String privateKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
byte[] bytes = toBytes(privateKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(bytes);
return keyFactory.generatePrivate(privateKeySpec);
}
public static PublicKey toPublicKey(String publicKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
byte[] bytes = toBytes(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(bytes);
return keyFactory.generatePublic(publicKeySpec);
}
private static String toString(byte[] barr) {
return Base64Encoder.encode(barr);
}
private static byte[] toBytes(String str) throws CoderException {
return Base64Encoder.decode(str);
}
public static KeyPair createKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(KEY_SIZE);
return kpg.genKeyPair();
}
public static byte[] encrypt(byte[] data, PrivateKey privateKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
int max=(KEY_SIZE/8)-11;
// we need to split in pieces, because RSA cannot handle pices bigger than the key size
List<byte[]> list=new ArrayList<byte[]>();
int offset=0,len=data.length,l,total=0;
byte[] part;
while(offset<len) {
l=len-offset<max?len-offset:max;
part=cipher.doFinal(data, offset, l);
total+=part.length;
list.add(part);
offset+=l;
}
// now we merge to one piece
byte[] bytes=new byte[total];
Iterator<byte[]> it = list.iterator();
int count=0;
while(it.hasNext()){
part=it.next();
for(int i=0;i<part.length;i++){
bytes[count++]=part[i];
}
}
return bytes;
}
public static byte[] decrypt(byte[] data, PublicKey publicKey, int offset) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
int max=(KEY_SIZE/8);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
// we need to split in pieces, because RSA cannot handle pieces bigger than the key size
List<byte[]> list=new ArrayList<byte[]>();
int off=offset,len=data.length,l,total=0;
byte[] part;
while(off<len) {
l=len-off<max?len-off:max;
part=cipher.doFinal(data, off, l);
total+=part.length;
list.add(part);
off+=l;
}
// now we merge to one piece
byte[] bytes=new byte[total];
Iterator<byte[]> it = list.iterator();
int count=0;
while(it.hasNext()){
part=it.next();
for(int i=0;i<part.length;i++){
bytes[count++]=part[i];
}
}
return bytes;
}
}