Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package rsa;
- import java.math.BigInteger;
- import java.util.ArrayList;
- import java.util.Random;
- import java.util.concurrent.atomic.AtomicLong;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- public class RSA {
- private final Random random;
- private BigInteger privateKey;
- private BigInteger publicKey;
- private BigInteger modulo;
- public static void main(String[] args) {
- RSA rsa = new RSA();
- rsa.generateNewKeypair(1024);
- BigInteger message = BigInteger.valueOf(1234);
- BigInteger encrypted = RSA.translate(message, rsa.getPublicKey(), rsa.getModulo());
- BigInteger decrypted = RSA.translate(encrypted, rsa.getPrivateKey(), rsa.getModulo());
- System.out.println("Encrypted: " + encrypted);
- System.out.println("Decrypted: " + decrypted);
- }
- public RSA() {
- random = new IntelRandom();
- }
- public static BigInteger translate(BigInteger message, BigInteger key, BigInteger module) {
- return message.modPow(key, module);
- }
- public BigInteger encode(BigInteger message) {
- return message.modPow(publicKey, modulo);
- }
- public BigInteger decode(BigInteger message) {
- return message.modPow(privateKey, modulo);
- }
- public BigInteger getModulo() {
- return modulo;
- }
- public BigInteger getPrivateKey() {
- return privateKey;
- }
- public BigInteger getPublicKey() {
- return publicKey;
- }
- public void generateNewKeypair(int bit) {
- BigInteger[] primes = generatePrimes(2, bit / 2);
- BigInteger p = primes[0];
- BigInteger q = primes[1];
- modulo = q.multiply(p);
- BigInteger pN = (q.subtract(BigInteger.valueOf(1))).multiply(p.subtract(BigInteger.valueOf(1)));
- publicKey = BigInteger.ZERO;
- while (publicKey.equals(BigInteger.ZERO)) {
- BigInteger rnd = new BigInteger(pN.bitLength(), random);
- if (rnd.compareTo(pN) <= 0 && rnd.gcd(pN).equals(BigInteger.ONE)) {
- publicKey = rnd;
- }
- }
- privateKey = publicKey.modInverse(modulo);
- }
- private BigInteger[] generatePrimes(int amount, int length) {
- final ModifiableFinal<Integer> mAmount = new ModifiableFinal<>(amount);
- final ArrayList<PrimeThread> threads = new ArrayList<>();
- int threadAmount = Runtime.getRuntime().availableProcessors();
- if (threadAmount < mAmount.getValue()) {
- threadAmount = mAmount.getValue();
- }
- final BigInteger[] primes = new BigInteger[mAmount.getValue()];
- for (int i = 0; i < threadAmount; i++) {
- final PrimeThread pt = new PrimeThread(length, random) {
- @Override
- public void onDone() {
- if (mAmount.getValue() != 0) {
- primes[primes.length - mAmount.getValue()] = this.getPrime();
- mAmount.setValue(mAmount.getValue() - 1);
- if (mAmount.getValue() == 0) {
- new Thread() {
- @Override
- public void run() {
- for (Thread t : threads) {
- t.stop();
- }
- }
- }.start();
- }
- }
- }
- };
- pt.start();
- threads.add(pt);
- }
- for (Thread thread : threads) {
- try {
- thread.join();
- } catch (InterruptedException ex) {
- Logger.getLogger(RSA.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
- return primes;
- }
- private static class PrimeThread extends Thread {
- private BigInteger prime = null;
- private final int length;
- private final Random random;
- public PrimeThread(int length, Random random) {
- this.length = length;
- this.random = random;
- }
- @Override
- public void run() {
- prime = BigInteger.probablePrime(length, random);
- onDone();
- }
- public BigInteger getPrime() {
- return prime;
- }
- public void onDone() {
- //Override this
- }
- }
- public static class IntelRandom extends Random {
- private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L);
- private static final long mask = (1L << 48) - 1;
- private static final long multiplier = 0x5DEECE66DL;
- private final AtomicLong seed;
- public IntelRandom() {
- seed = new AtomicLong(initialScramble(seedUniquifier() ^ System.nanoTime()));
- }
- private static long initialScramble(long seed) {
- return (seed ^ multiplier) & mask;
- }
- private static long seedUniquifier() {
- for (;;) {
- long current = seedUniquifier.get();
- long next = current * 181783497276652981L;
- if (seedUniquifier.compareAndSet(current, next)) {
- return next;
- }
- }
- }
- @Override
- public void nextBytes(byte[] bytes) {
- for (int i = 0, len = bytes.length; i < len;) {
- for (int rnd = nextInt(),
- n = Math.min(len - i, Integer.SIZE / Byte.SIZE);
- n-- > 0; rnd >>= Byte.SIZE) {
- bytes[i++] = (byte) rnd;
- }
- }
- }
- @Override
- public int nextInt() {
- return next(seed, 32);
- }
- private static int next(AtomicLong seed, int nbits) {
- long x = seed.get();
- x ^= (x << 21);
- x ^= (x >>> 35);
- x ^= (x << 4);
- seed.set(x);
- x &= ((1L << nbits) - 1);
- return (int) x;
- }
- }
- public class ModifiableFinal<T> {
- private T value;
- public ModifiableFinal() {
- }
- public ModifiableFinal(T initialValue) {
- this.value = initialValue;
- }
- public void setValue(T newValue) {
- this.value = newValue;
- }
- public T getValue() {
- return this.value;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement