package zeta.crypto;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import zeta.util.Base64;
import zeta.util.StreamUtils;
public class Encrypter {
public Encrypter(Key key) {
this.key = key;
}
public void encrypt(int randomize, String inFilename, String outFilename) throws IOException {
String inZip = inFilename + ".bz2";
new File(inZip).delete();
FileInputStream in = null;
FileOutputStream out = null;
try {
bzip2CompressData(inFilename, inZip);
in = new FileInputStream(inZip);
out = new FileOutputStream(outFilename);
encrypt(randomize, new File(inZip).length(), in, out);
} finally {
StreamUtils.close(in);
StreamUtils.close(out);
new File(inZip).delete();
}
}
public void encrypt(int randomize, long inLength, InputStream in, OutputStream out) throws IOException {
SecureRandom random = new SecureRandom(key.getGenerator().modPow(BigInteger.valueOf(System.currentTimeMillis()*randomize), key.getModulo()).toByteArray());
String s = String.valueOf(inLength) + ';';
out.write(s.getBytes());
BigInteger x;
final BigInteger TWO = new BigInteger("2");
do {
byte[] buffer = new byte[KEY_LENGTH/8];
random.nextBytes(buffer);
buffer[0] &= 63;
x = new BigInteger(buffer);
x = x.mod(key.getModulo()).subtract(TWO);
} while ((x.bitLength()+31)/32 < 3);
IONumber.write(key.getGenerator().modPow(x, key.getModulo()), out, true);
x = key.getBase().modPow(x, key.getModulo());
byte[] buffer = new byte[4*((key.getModulo().bitLength()+31)/32-1)+1];
buffer[0] = 0;
boolean eof = false;
while (!eof) {
int pos = 1;
while (pos < buffer.length) {
int n = in.read(buffer, pos, buffer.length-pos);
if (n <= 0) {
eof = (n == -1);
break;
}
pos += n;
}
if (pos == 1) {
break;
}
if (pos < buffer.length) {
int sz = 4*((pos+2)/4)+1;
byte[] tmp = new byte[sz];
System.arraycopy(buffer, 0, tmp, 0, pos); Arrays.fill(tmp, pos, sz, (byte)0);
pos = sz;
buffer = tmp;
}
for (int i = 1; i < pos; i += 4) {
byte b = buffer[i];
buffer[i] = buffer[i+3];
buffer[i+3] = b;
b = buffer[i+1];
buffer[i+1] = buffer[i+2];
buffer[i+2] = b;
}
BigInteger n = new BigInteger(buffer);
IONumber.write(n.multiply(x).mod(key.getModulo()), out, true);
}
}
public String encryptURLFile(String urlFile) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
ZipOutputStream zip = new ZipOutputStream(out);
zip.setLevel(Deflater.BEST_COMPRESSION);
zip.putNextEntry(new ZipEntry("param"));
int idx = urlFile.indexOf('?');
StreamUtils.writeData(new ByteArrayInputStream(urlFile.substring(idx+1).getBytes("UTF-8")), zip, true, true);
byte[] data = out.toByteArray();
ByteArrayOutputStream out2 = new ByteArrayOutputStream(2048);
encrypt(new SecureRandom().nextInt(1024), data.length, new ByteArrayInputStream(data), out2);
data = out2.toByteArray();
StringBuffer buffer = new StringBuffer(2*data.length);
if (idx >= 0) {
buffer.append(urlFile.substring(0, idx+1));
}
buffer.append("param=");
buffer.append(Base64.encode(data));
return buffer.toString();
}
public static void bzip2CompressData(String inFilename, String outFilename) throws IOException {
BufferedInputStream in = null;
BufferedOutputStream out = null;
org.apache.tools.bzip2.CBZip2OutputStream bzout = null;
try {
in = new BufferedInputStream(new FileInputStream(inFilename));
out = new BufferedOutputStream(new FileOutputStream(outFilename));
out.write('B');
out.write('Z');
int ch = in.read();
if (ch != -1) { bzout = new org.apache.tools.bzip2.CBZip2OutputStream(out);
do {
bzout.write(ch);
ch = in.read();
} while (ch != -1);
bzout.flush();
}
} finally {
StreamUtils.close(in);
StreamUtils.close(bzout);
StreamUtils.close(out);
}
}
public static void main(String[] args) {
try {
File[] list = new File(".").listFiles();
if (list != null) {
zeta.util.Properties properties = new zeta.util.Properties();
String key = properties.get("key", "");
for (int i = 0; i < list.length; ++i) {
String s = list[i].getName();
if (!s.equals("e.$$$") && !s.equals("d.$$$") && !list[i].isDirectory()) {
System.out.print(s + ": ");
System.out.flush();
Encrypter e = new Encrypter(new DefaultKeyEncrypt());
Decrypter d = new Decrypter(new DefaultKeyEncrypt());
e.encrypt(111, s, "e.$$$");
d.decrypt(key, "e.$$$", "d.$$$");
FileInputStream fin1 = new FileInputStream(s);
FileInputStream fin2 = new FileInputStream("d.$$$");
if (StreamUtils.compare(fin1, fin2)) {
System.out.println("ok");
} else {
System.out.println("NOT ok!");
return;
}
fin1.close();
fin2.close();
}
System.gc();
System.out.println("Memory: " + (Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()));
}
}
} catch (Exception e) {
zeta.util.ThrowableHandler.handle(e);
}
}
private Key key;
private final int KEY_LENGTH = 1024;
}