001package lucee.commons.digest; 002 003import java.io.IOException; 004import java.security.InvalidKeyException; 005import java.security.KeyFactory; 006import java.security.KeyPair; 007import java.security.KeyPairGenerator; 008import java.security.NoSuchAlgorithmException; 009import java.security.PrivateKey; 010import java.security.PublicKey; 011import java.security.spec.InvalidKeySpecException; 012import java.security.spec.PKCS8EncodedKeySpec; 013import java.security.spec.X509EncodedKeySpec; 014import java.util.ArrayList; 015import java.util.Iterator; 016import java.util.List; 017 018import javax.crypto.BadPaddingException; 019import javax.crypto.Cipher; 020import javax.crypto.IllegalBlockSizeException; 021import javax.crypto.NoSuchPaddingException; 022 023import lucee.runtime.coder.CoderException; 024 025public class RSA { 026 027 private static final int KEY_SIZE = 1024; 028 029 public static String toString(PrivateKey privateKey) { 030 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded()); 031 return toString(pkcs8EncodedKeySpec.getEncoded()); 032 } 033 034 public static String toString(PublicKey publicKey) { 035 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded()); 036 return toString(x509EncodedKeySpec.getEncoded()); 037 } 038 039 public static PrivateKey toPrivateKey(String privateKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { 040 byte[] bytes = toBytes(privateKey); 041 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 042 PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(bytes); 043 return keyFactory.generatePrivate(privateKeySpec); 044 } 045 046 public static PublicKey toPublicKey(String publicKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { 047 byte[] bytes = toBytes(publicKey); 048 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 049 X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(bytes); 050 return keyFactory.generatePublic(publicKeySpec); 051 } 052 053 private static String toString(byte[] barr) { 054 return Base64Encoder.encode(barr); 055 } 056 057 private static byte[] toBytes(String str) throws CoderException { 058 return Base64Encoder.decode(str); 059 } 060 061 public static KeyPair createKeyPair() throws NoSuchAlgorithmException { 062 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 063 kpg.initialize(KEY_SIZE); 064 return kpg.genKeyPair(); 065 } 066 067 public static byte[] encrypt(byte[] data, PrivateKey privateKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { 068 Cipher cipher = Cipher.getInstance("RSA"); 069 cipher.init(Cipher.ENCRYPT_MODE, privateKey); 070 int max=(KEY_SIZE/8)-11; 071 072 // we need to split in pieces, because RSA cannot handle pices bigger than the key size 073 List<byte[]> list=new ArrayList<byte[]>(); 074 int offset=0,len=data.length,l,total=0; 075 byte[] part; 076 while(offset<len) { 077 l=len-offset<max?len-offset:max; 078 part=cipher.doFinal(data, offset, l); 079 total+=part.length; 080 list.add(part); 081 offset+=l; 082 } 083 084 // now we merge to one piece 085 byte[] bytes=new byte[total]; 086 Iterator<byte[]> it = list.iterator(); 087 int count=0; 088 while(it.hasNext()){ 089 part=it.next(); 090 for(int i=0;i<part.length;i++){ 091 bytes[count++]=part[i]; 092 } 093 } 094 095 096 return bytes; 097 } 098 099 public static byte[] decrypt(byte[] data, PublicKey publicKey, int offset) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { 100 int max=(KEY_SIZE/8); 101 Cipher cipher = Cipher.getInstance("RSA"); 102 cipher.init(Cipher.DECRYPT_MODE, publicKey); 103 104 105 // we need to split in pieces, because RSA cannot handle pieces bigger than the key size 106 List<byte[]> list=new ArrayList<byte[]>(); 107 int off=offset,len=data.length,l,total=0; 108 byte[] part; 109 while(off<len) { 110 l=len-off<max?len-off:max; 111 part=cipher.doFinal(data, off, l); 112 total+=part.length; 113 list.add(part); 114 off+=l; 115 } 116 117 // now we merge to one piece 118 byte[] bytes=new byte[total]; 119 Iterator<byte[]> it = list.iterator(); 120 int count=0; 121 while(it.hasNext()){ 122 part=it.next(); 123 for(int i=0;i<part.length;i++){ 124 bytes[count++]=part[i]; 125 } 126 } 127 128 return bytes; 129 } 130 131 /*public static void main(String[] args) throws Exception { 132 KeyPair kp = createKeyPair(); 133 String str=""; 134 for(int i=0;i<=1700;i++) { 135 136 str+=i+"Hello there how are you?\n"; 137 } 138 byte[] bytes = str.getBytes(); 139 140 long start=System.currentTimeMillis(); 141 byte[] enc = encrypt(bytes, kp.getPrivate()); 142 143 System.out.println(enc.length); 144 byte[] dec = decrypt(enc, kp.getPublic()); 145 System.out.println(new String(dec)); 146 System.out.println("->"+(System.currentTimeMillis()-start)); 147 }*/ 148 149}