com.fasteasytrade.jrandtest.algo.RSACrypt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ports-jrandtest Show documentation
Show all versions of ports-jrandtest Show documentation
Fork from https://github.com/cryptopony/jrandtest
The newest version!
/*
* Created on 16/03/2005
*
* JRandTest package
*
* Copyright (c) 2005, Zur Aougav, [email protected]
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* Neither the name of the JRandTest nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.fasteasytrade.jrandtest.algo;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Vector;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* Java RSA algorithm implementation.
*
*
* 2 Sep 2003: Zur Aougav
* 2 Sep 2003: Copyright (c) 2003 Zur Aougav
* 2 Sep 2003: New RSA java class.
* 2 Sep 2003: Use simple securerandom class to generate p & q primes.
* 2 Sep 2003: Read and write biginteger to/from streams as object or simple outputstream (with length).
* 2 Sep 2003: Vector encrypt(byte[] message) does not handle the last bytes properly. Buffer
* is filled with 0. Decryption will have 0 (nulls) at end of decoded string.
* 3 Sep 2003: Add test in main: Shall I compare thee to a summer's day. Shakespeare.
* 3 Sep 2003: Add save/loadPublicKey and save/loadPrivateKey.
* 3 Sep 2003: Add -g option: to generate and print keys.
* 3 Sep 2003: Add -gs option: to generate and save keys in rsapublic.key and rsaprivate.key.
* 3 Sep 2003: Add encryptFile(infilename,outfilename) and decryptFile(infilename,outfilename).
* 4 Sep 2003: Add GZIP support.
* encryptFileGzip(infilename,outfilename) and decryptFileGzip(infilename,outfilename).
* 4 Sep 2003: Changed default e=3 to e=65537.
* 17 Mar 2005: encrypt (0 || random 32 bits || data).
*
*
* @author Zur Aougav
*/
public class RSACrypt extends Cipher {
BigInteger n, d, e;
int msglen;
java.util.Random rnd = new java.util.Random();
/**
* Almost null contructor
*/
public RSACrypt() {
msglen = -1;
}
/**
* Generate public and private keys based on two primes, p and q,
* we make public (n, e), and private (n, d).
* We discard p and q.
*/
public void generateKeys(int bitlen) {
SecureRandom r = new SecureRandom();
BigInteger p = new BigInteger(bitlen / 2, 200, r);
BigInteger q = new BigInteger(bitlen / 2, 200, r);
n = p.multiply(q);
BigInteger m = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
e = new BigInteger("65537");
while (m.gcd(e).intValue() > 1) {
e = e.add(new BigInteger("2"));
}
d = e.modInverse(m);
}
/**
* Encrypt one big integer
*/
public BigInteger encrypt(BigInteger message) {
return message.modPow(e, n);
}
/**
* Decrypt one big integer
*/
public BigInteger decrypt(BigInteger message) {
return message.modPow(d, n);
}
/**
* encrypt byte[] and returns vector of bigintegers.
*/
public Vector encrypt(byte[] message) {
return encrypt(message, message.length);
}
/**
* encrypt byte[] and returns vector of bigintegers.
* encrypt just the first mlen bytes.
*
* Encrypt:
* byte 0 : 0
* byte 1 - 4 = random number
* byte 5 .. getMessageLen-1 = data
*/
public Vector encrypt(byte[] message, int mlen) {
if (mlen < 1) {
return null;
}
int numMsgs = 1 + (mlen - 1) / (getMessageLength() - 5);
int rest = mlen % (getMessageLength() - 5);
Vector rslt = new Vector();
byte[] tmp = new byte[getMessageLength()];
int i, x;
int j = 0; // read from message buffer
for (i = 0; i < numMsgs; i++) {
Arrays.fill(tmp, 0, getMessageLength(), (byte)0);
x = rnd.nextInt();
tmp[1] = (byte)(x >> 24);
tmp[2] = (byte)(x >> 16);
tmp[3] = (byte)(x >> 8);
tmp[4] = (byte)x;
int k = getMessageLength() - 5;
if (i + 1 == numMsgs && rest > 0) {
k = rest;
}
for (int t = 0; t < k; t++) {
tmp[t + 5] = message[j++];
}
BigInteger v = new BigInteger(tmp);
rslt.add(encrypt(v));
}
return rslt;
}
/**
* encrypt infile to outfile.
*/
public void encryptFile(String infile, String outfile) throws IOException {
FileInputStream fis = new FileInputStream(infile);
DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile));
byte[] buffer = new byte[getMessageLength() - 5];
int len;
while (true) {
len = fis.read(buffer, 0, buffer.length);
if (len < 0) {
break; // End of encryption
}
out.writeInt(len); // write length of data
Vector vec = encrypt(buffer);
if (vec.size() != 1) {
fis.close();
throw new IOException("encrypt does not return a biginteger!");
}
write(vec.elementAt(0), out); // write biginteger
}
out.writeInt(-1); // write "dummy" EOF - no more bigintegers
out.close();
fis.close();
}
/**
* decrypt infile to outfile.
*/
public void decryptFile(String infile, String outfile) throws IOException {
DataInputStream in = new DataInputStream(new FileInputStream(infile));
FileOutputStream fos = new FileOutputStream(outfile);
int len; // real len of data
BigInteger v; // read bigintegers from inputfile
while (true) {
len = in.readInt(); // read len of data
//if (len < 0) // Found our "dummy" EOF?
if (len < 5) {
break; // End of decryption
}
v = read(in); // read biginteger
byte[] buffer = decrypt(v).toByteArray();
//fos.write(buffer, 0,len); // write just the len data, not more
fos.write(buffer, 5, len - 5); // write just the len data, not more
}
fos.close();
in.close();
}
/**
* encrypt infile to outfile with compression.
*/
public void encryptFileGzip(String infile, String outfile) throws IOException {
FileInputStream fis = new FileInputStream(infile);
GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(outfile));
byte[] buffer = new byte[getMessageLength() - 5];
int len;
while (true) {
len = fis.read(buffer, 0, buffer.length);
if (len < 0) {
break; // End of encryption
}
write(len, out); // write length of data
Vector vec = encrypt(buffer);
if (vec.size() != 1) {
fis.close();
throw new IOException("encrypt does not return a biginteger!");
}
write(vec.elementAt(0), out); // write biginteger
}
write(-1, out); // write "dummy" EOF - no more bigintegers
out.close();
fis.close();
}
/*
* decrypt compressed infile to outfile.
*/
public void decryptFileGzip(String infile, String outfile) throws IOException {
GZIPInputStream in = new GZIPInputStream(new FileInputStream(infile));
FileOutputStream fos = new FileOutputStream(outfile);
int len; // real len of data
BigInteger v; // read bigintegers from inputfile
while (true) {
len = readInt(in); // read len of data
//if (len < 0) // Found our "dummy" EOF?
if (len < 5) {
break; // End of decryption
}
v = readBigInteger(in); // read biginteger
byte[] buffer = decrypt(v).toByteArray();
//fos.write(buffer, 0,len); // write just the len data, not more
fos.write(buffer, 5, len - 5); // write just the len data, not more
}
fos.close();
in.close();
}
/**
* Returns message length in bytes. Based on n.
*/
public int getMessageLength() {
if (msglen == -1) {
msglen = n.bitLength() / 8;
}
return msglen;
}
/**
* Write one big integer to outputstream, including length.
*/
public static void write(BigInteger v, DataOutputStream out) throws IOException {
byte[] buffer = v.toByteArray();
int len = buffer.length;
out.writeInt(len);
out.write(buffer);
}
/**
* Write one big integer to outputstream, as java object.
*/
public static void write(BigInteger v, ObjectOutputStream out) throws IOException {
out.writeObject(v);
}
/**
* Write int to GZIPOutputStream
*/
public static void write(int v, GZIPOutputStream out) throws IOException {
out.write(v >>> 24); // write Cxxx of v
out.write(0xff & (v >>> 16)); // write xCxx of v
out.write(0xff & (v >>> 8)); // write xxCx of v
out.write(0xff & v); // write xxxC of v
}
/**
* Write one big integer to GZIPoutputstream, including length.
*/
public static void write(BigInteger v, GZIPOutputStream out) throws IOException {
byte[] buffer = v.toByteArray();
int len = buffer.length;
write(len, out);
out.write(buffer);
}
/**
* Read one big integer from inputstream. First read length, second read bytes to
* build the new big integer.
*/
public static BigInteger read(DataInputStream in) throws IOException {
int len = in.readInt(); // read length of bigintegers in bytes
byte[] buffer = new byte[len]; // alloc array for biginteger
int k = in.read(buffer, 0, len);// read it
if (k != len) {
throw new IOException("read biginteger fail. Expect " + len + " bytes. Read " + k + " bytes.");
}
return new BigInteger(buffer);
}
/**
* Read one big integer from inputstream, as java object.
*/
public static BigInteger read(ObjectInputStream in) throws IOException, ClassNotFoundException {
BigInteger v = (BigInteger)in.readObject();
return v;
}
/**
* Read int from GZIPinputstream.
*/
public static int readInt(GZIPInputStream in) throws IOException {
int v;
v = in.read() << 24; // read first byte
v |= in.read() << 16; // read second byte
v |= in.read() << 8; // read third byte
v |= in.read(); // read fourth byte
return v;
}
/**
* Read one big integer from GZIPinputstream. First read length, second read bytes to
* build the new big integer.
*/
public static BigInteger readBigInteger(GZIPInputStream in) throws IOException {
int len = readInt(in); // read length of bigintegers in bytes
byte[] buffer = new byte[len]; // alloc array for biginteger
int k = 0; // index/location into buffer to read data
// we must read in a loop cause GZIP can bring parts of the data
while (len > 0) { // still len to read from GZIP?
int i = in.read(buffer, k, len);// read next part to fill buffer
k += i; // next location in buffer
len -= i; // less to read from total/original len
}
return new BigInteger(buffer);
}
/**
* Save public key to file
*/
public void savePublicKey(String outfilename) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(outfilename));
write(n, out);
write(e, out);
out.close();
}
/**
* Load public key from file
*/
public void loadPublicKey(String infilename) throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(infilename));
n = read(in);
e = read(in);
in.close();
}
/**
* Save private key to file
*/
public void savePrivateKey(String outfilename) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(outfilename));
write(n, out);
write(d, out);
out.close();
}
/**
* Load private key from file
*/
public void loadPrivateKey(String infilename) throws IOException, ClassNotFoundException {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(infilename));
n = read(in);
d = read(in);
in.close();
}
/**
* Just testing RSA class
*/
public static void test1() {
RSACrypt rsa = new RSACrypt();
rsa.generateKeys(128);
String mymsg = "Shall I compare thee to a summer\'s day?\n" + "Thou art more lovely and more temperate.\n" + "Rough winds do shake the darling buds of May,\n" + "And summer\'s lease hath all too short a date.\n" + "Sometime too hot the eye of heaven shines,\n" + "And often is his gold complexion dimmed,\n" + "And every fair from fair sometime declines,\n" + "By chance or nature\'s changing course untrimmed;\n" + "But thy eternal summer shall not fade\n" + "Nor lose possession of that fair thou ow\'st,\n" + "Nor shall death brag thou wander\'st in his shade\n" + "When in eternal lines to time thou grow\'st.\n" + " So long as men can breathe or eyes can see,\n" + " So long lives this, and this gives life to thee.\n" + "\n" + "Sonnet 18, William Shakespeare\n" + "";
byte[] mymsgb = mymsg.getBytes();
Vector v = rsa.encrypt(mymsgb);
for (int i = 0; i < v.size(); i++) {
BigInteger t = v.elementAt(i);
System.out.print(new String(rsa.decrypt(t).toByteArray()));
}
}
/**
* Print usage of main RSA class
*/
public static void usage() {
System.out.println("RSACrypt.java class\n" + "Copyright (c) 2003 Zur Aougav\n" + "Usage: \n" + " java RSA -g : to generate and print keys\n" + " java RSA -gs : to generate and save keys\n" + " java RSA -t : test generate, crypt and decrypt sonnet\n" + " java RSA -c infile outfile: load public keys and crypt infile to gzip outfile\n" + " java RSA -d infile outfile: load private keys and decrypt gzip infile to outfile\n" + " java RSA -cs infile outfile: load public keys and crypt infile to outfile\n" + " java RSA -ds infile outfile: load private keys and decrypt infile to outfile");
}
/**
* Main to test several options of class
*/
public static void main(String[] args) {
int bitlen = 256;
if (args.length == 1) {
if (args[0].equals("-g")) { // Generate keys and print
RSACrypt rsa = new RSACrypt();
rsa.generateKeys(bitlen);
System.out.println("Generate keys:");
System.out.println("Public key: " + rsa.n.toString() + "," + rsa.e.toString());
System.out.println("Private key: " + rsa.n.toString() + "," + rsa.d.toString());
return;
}
if (args[0].equals("-gs")) { // Generate keys and save
RSACrypt rsa = new RSACrypt();
System.out.println("Generate keys...");
rsa.generateKeys(bitlen);
try {
System.out.println("Save public key to rsapublic.key...");
rsa.savePublicKey("rsapublic.key");
System.out.println("Save public key to rsaprivate.key...");
rsa.savePrivateKey("rsaprivate.key");
} catch (IOException e) {
System.out.println(e);
}
return;
}
if (args[0].equals("-t")) { // Encrypt/Decrypt Sonnet
test1();
return;
}
}
if (args.length == 3 && (args[0].equals("-c") || args[0].equals("-d") || args[0].equals("-cs") || args[0].equals("-ds"))) {
RSACrypt rsa = new RSACrypt();
try {
if (args[0].equals("-c") || args[0].equals("-cs")) {// Encrypt?
System.out.println("Load public key from rsapublic.key...");
rsa.loadPublicKey("rsapublic.key");
System.out.println("Encrypt " + args[1] + " into " + args[2] + "...");
if (args[0].equals("-cs")) {
rsa.encryptFile(args[1], args[2]);
} else {
rsa.encryptFileGzip(args[1], args[2]);
}
} else { // Decrypt
System.out.println("Load private key from rsaprivate.key...");
rsa.loadPrivateKey("rsaprivate.key");
System.out.println("Decrypt " + args[1] + " into " + args[2] + "...");
if (args[0].equals("-ds")) {
rsa.decryptFile(args[1], args[2]);
} else {
rsa.decryptFileGzip(args[1], args[2]);
}
}
} catch (IOException e) {
System.out.println(e);
} catch (ClassNotFoundException ec) {
System.out.println(ec);
}
return;
} // end encrypt/decrypt
usage(); // unknown parameters
return;
} // end main
} // end RSA class
© 2015 - 2025 Weber Informatics LLC | Privacy Policy