make work on browser (almost)
This commit is contained in:
parent
698dde0809
commit
b52a72e5a4
39316
javascript/classes.js
39316
javascript/classes.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
package net.minecraft.src;
|
||||
package me.ayunami2000.ayuncraft;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -17,6 +17,7 @@ import java.security.SecureRandom;
|
|||
import java.security.Security;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
|
@ -239,4 +240,4 @@ public class CryptManager
|
|||
{
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,11 +2,12 @@ package net.lax1dude.eaglercraft;
|
|||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.src.*;
|
||||
import me.ayunami2000.ayuncraft.CryptManager;
|
||||
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
@ -15,7 +16,8 @@ public class WebsocketNetworkManager implements INetworkManager {
|
|||
private boolean isInputBeingDecrypted;
|
||||
private boolean isOutputEncrypted;
|
||||
private SecretKey sharedKeyForEncryption;
|
||||
private PrivateKey privateKey;
|
||||
|
||||
private final boolean logpackets=true;
|
||||
|
||||
private BufferedBlockCipher inputBufferedBlockCipher=null;
|
||||
private BufferedBlockCipher outputBufferedBlockCipher=null;
|
||||
|
@ -23,14 +25,7 @@ public class WebsocketNetworkManager implements INetworkManager {
|
|||
private NetHandler netHandler;
|
||||
|
||||
public WebsocketNetworkManager(String uri, String eagler, NetHandler netHandler) throws IOException {
|
||||
this(uri,eagler,netHandler,(PrivateKey)null);
|
||||
//this(uri,eagler,netHandler,CryptManager.createNewKeyPair().getPrivate());
|
||||
}
|
||||
|
||||
public WebsocketNetworkManager(String uri, String eagler, NetHandler netHandler, PrivateKey privKey) throws IOException {
|
||||
this.netHandler = netHandler;
|
||||
this.privateKey = privKey;
|
||||
//this.sharedKeyForEncryption = CryptManager.createNewSharedKey();
|
||||
this.sharedKeyForEncryption = null;
|
||||
this.isInputBeingDecrypted = false;
|
||||
this.isOutputEncrypted = false;
|
||||
|
@ -49,7 +44,7 @@ public class WebsocketNetworkManager implements INetworkManager {
|
|||
public void addToSendQueue(Packet var1) {
|
||||
try {
|
||||
sendBuffer.reset();
|
||||
//the following attempts to keep packets encrypted because i forgot that last code i sent lol
|
||||
|
||||
DataOutputStream yee;
|
||||
if(this.isOutputEncrypted&&!(var1 instanceof Packet252SharedKey)){
|
||||
yee = this.encryptOuputStream();
|
||||
|
@ -59,15 +54,11 @@ public class WebsocketNetworkManager implements INetworkManager {
|
|||
|
||||
if (Minecraft.getMinecraft().gameSettings.useDefaultProtocol && var1 instanceof Packet252SharedKey && !this.isOutputEncrypted)
|
||||
{
|
||||
if (!this.netHandler.isServerHandler())
|
||||
{
|
||||
this.sharedKeyForEncryption = ((Packet252SharedKey)var1).getSharedKey();
|
||||
}
|
||||
this.sharedKeyForEncryption = ((Packet252SharedKey)var1).getSharedKey();
|
||||
this.isOutputEncrypted=true;
|
||||
//yee=this.encryptOuputStream(yee);
|
||||
}
|
||||
Packet.writePacket(var1, yee);
|
||||
//System.out.println("SENDING: "+var1);
|
||||
yee.flush();
|
||||
EaglerAdapter.writePacket(sendBuffer.toByteArray());
|
||||
} catch (IOException e) {
|
||||
|
@ -162,7 +153,7 @@ public class WebsocketNetworkManager implements INetworkManager {
|
|||
decStream.mark();
|
||||
try {
|
||||
Packet pkt = Packet.readPacket(packetStream, false);
|
||||
//System.out.println("RECEIVING: " + pkt);
|
||||
if(logpackets)System.out.println("RECEIVING: " + pkt);
|
||||
pkt.processPacket(this.netHandler);
|
||||
} catch (EOFException e) {
|
||||
decStream.reset();
|
||||
|
@ -182,19 +173,17 @@ public class WebsocketNetworkManager implements INetworkManager {
|
|||
}else {
|
||||
DataInputStream packetStream = new DataInputStream(new ByteBufferDirectInputStream(stream));
|
||||
while (stream.hasRemaining()) {
|
||||
if(logpackets)System.out.println("FARD");
|
||||
stream.mark();
|
||||
try {
|
||||
Packet pkt = Packet.readPacket(packetStream, false);
|
||||
boolean change=false;
|
||||
if (pkt != null) {
|
||||
if (Minecraft.getMinecraft().gameSettings.useDefaultProtocol && pkt instanceof Packet252SharedKey && !this.isInputBeingDecrypted) {
|
||||
if (this.netHandler.isServerHandler()) {
|
||||
this.sharedKeyForEncryption = ((Packet252SharedKey) pkt).getSharedKey(this.privateKey);
|
||||
}
|
||||
packetStream = this.decryptInputStream(new ByteBufferDirectInputStream(stream));
|
||||
change=true;
|
||||
}
|
||||
//System.out.println("RECEIVING: " + pkt);
|
||||
if(logpackets)System.out.println("RECEIVING: " + pkt);
|
||||
pkt.processPacket(this.netHandler);
|
||||
if(change){
|
||||
processReadPackets();
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.security.PrivateKey;
|
|||
import java.security.PublicKey;
|
||||
import java.util.*;
|
||||
|
||||
import me.ayunami2000.ayuncraft.CryptManager;
|
||||
import net.lax1dude.eaglercraft.DefaultSkinRenderer;
|
||||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||
import net.lax1dude.eaglercraft.EaglerProfile;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import me.ayunami2000.ayuncraft.CryptManager;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -73,7 +75,7 @@ public class Packet252SharedKey extends Packet
|
|||
*/
|
||||
public SecretKey getSharedKey()
|
||||
{
|
||||
return this.getSharedKey((PrivateKey)null);
|
||||
return this.getSharedKey(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import me.ayunami2000.ayuncraft.CryptManager;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package org.bouncycastle.crypto;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
public class CipherKeyGenerator
|
||||
{
|
||||
protected SecureRandom random;
|
||||
protected Random random;
|
||||
protected int strength;
|
||||
|
||||
public void init(KeyGenerationParameters par1)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package org.bouncycastle.crypto;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
public class KeyGenerationParameters
|
||||
{
|
||||
private SecureRandom random;
|
||||
private Random random;
|
||||
private int strength;
|
||||
|
||||
public KeyGenerationParameters(SecureRandom par1SecureRandom, int par2)
|
||||
public KeyGenerationParameters(Random par1SecureRandom, int par2)
|
||||
{
|
||||
this.random = par1SecureRandom;
|
||||
this.strength = par2;
|
||||
|
@ -16,7 +16,7 @@ public class KeyGenerationParameters
|
|||
/**
|
||||
* Return the random source associated with this generator.
|
||||
*/
|
||||
public SecureRandom getRandom()
|
||||
public Random getRandom()
|
||||
{
|
||||
return this.random;
|
||||
}
|
||||
|
|
34
src/teavm/java/java/security/Key.java
Normal file
34
src/teavm/java/java/security/Key.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package java.security;
|
||||
|
||||
public interface Key {
|
||||
public String getAlgorithm();
|
||||
|
||||
public String getFormat();
|
||||
|
||||
public byte[] getEncoded();
|
||||
}
|
29
src/teavm/java/java/security/PrivateKey.java
Normal file
29
src/teavm/java/java/security/PrivateKey.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package java.security;
|
||||
|
||||
public interface PrivateKey extends Key, javax.security.auth.Destroyable {
|
||||
}
|
29
src/teavm/java/java/security/PublicKey.java
Normal file
29
src/teavm/java/java/security/PublicKey.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package java.security;
|
||||
|
||||
public interface PublicKey extends Key {
|
||||
}
|
28
src/teavm/java/java/security/spec/KeySpec.java
Normal file
28
src/teavm/java/java/security/spec/KeySpec.java
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package java.security.spec;
|
||||
|
||||
public interface KeySpec { }
|
6
src/teavm/java/javax/crypto/SecretKey.java
Normal file
6
src/teavm/java/javax/crypto/SecretKey.java
Normal file
|
@ -0,0 +1,6 @@
|
|||
package javax.crypto;
|
||||
|
||||
import java.security.Key;
|
||||
|
||||
public interface SecretKey extends Key {
|
||||
}
|
80
src/teavm/java/javax/crypto/spec/SecretKeySpec.java
Normal file
80
src/teavm/java/javax/crypto/spec/SecretKeySpec.java
Normal file
|
@ -0,0 +1,80 @@
|
|||
package javax.crypto.spec;
|
||||
|
||||
import java.security.spec.KeySpec;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
public class SecretKeySpec implements KeySpec, SecretKey {
|
||||
private String algorithm;
|
||||
private byte[] key;
|
||||
|
||||
public String getAlgorithm() {
|
||||
return this.algorithm;
|
||||
}
|
||||
|
||||
public String getFormat() {
|
||||
return "RAW";
|
||||
}
|
||||
|
||||
public byte[] getEncoded() {
|
||||
byte[] tmp = new byte[this.key.length];
|
||||
System.arraycopy(this.key, 0, tmp, 0, tmp.length);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int code = this.algorithm.toUpperCase().hashCode();
|
||||
|
||||
for(int i = 0; i != this.key.length; ++i) {
|
||||
code ^= this.key[i] << 8 * (i % 4);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj != null && obj instanceof SecretKeySpec) {
|
||||
SecretKeySpec spec = (SecretKeySpec)obj;
|
||||
if (!this.algorithm.equalsIgnoreCase(spec.algorithm)) {
|
||||
return false;
|
||||
} else if (this.key.length != spec.key.length) {
|
||||
return false;
|
||||
} else {
|
||||
for(int i = 0; i != this.key.length; ++i) {
|
||||
if (this.key[i] != spec.key[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public SecretKeySpec(byte[] key, String algorithm) {
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("null key passed");
|
||||
} else if (algorithm == null) {
|
||||
throw new IllegalArgumentException("null algorithm passed");
|
||||
} else {
|
||||
this.key = new byte[key.length];
|
||||
System.arraycopy(key, 0, this.key, 0, key.length);
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
}
|
||||
|
||||
public SecretKeySpec(byte[] key, int offset, int len, String algorithm) {
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("Null key passed");
|
||||
} else if (key.length - offset < len) {
|
||||
throw new IllegalArgumentException("Bad offset/len");
|
||||
} else if (algorithm == null) {
|
||||
throw new IllegalArgumentException("Null algorithm string passed");
|
||||
} else {
|
||||
this.key = new byte[len];
|
||||
System.arraycopy(key, offset, this.key, 0, len);
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package javax.security.auth;
|
||||
|
||||
public class DestroyFailedException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -7790152857282749162L;
|
||||
|
||||
public DestroyFailedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DestroyFailedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
36
src/teavm/java/javax/security/auth/Destroyable.java
Normal file
36
src/teavm/java/javax/security/auth/Destroyable.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package javax.security.auth;
|
||||
|
||||
public interface Destroyable {
|
||||
public default void destroy() throws DestroyFailedException {
|
||||
throw new DestroyFailedException();
|
||||
}
|
||||
|
||||
public default boolean isDestroyed() {
|
||||
return false;
|
||||
}
|
||||
}
|
99
src/teavm/java/me/ayunami2000/ayuncraft/CryptManager.java
Normal file
99
src/teavm/java/me/ayunami2000/ayuncraft/CryptManager.java
Normal file
|
@ -0,0 +1,99 @@
|
|||
package me.ayunami2000.ayuncraft;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||
import org.bouncycastle.crypto.engines.AESFastEngine;
|
||||
import org.bouncycastle.crypto.io.CipherInputStream;
|
||||
import org.bouncycastle.crypto.io.CipherOutputStream;
|
||||
import org.bouncycastle.crypto.modes.CFBBlockCipher;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class CryptManager
|
||||
{
|
||||
//i hate security !!
|
||||
/**
|
||||
* Generate a new shared secret AES key from a static preset key
|
||||
*/
|
||||
private static final byte[] baseSharedKey = new byte[] {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
|
||||
public static SecretKey createNewSharedKey(){
|
||||
return new SecretKeySpec(baseSharedKey,"AES");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PublicKey from encoded X.509 data
|
||||
*/
|
||||
public static PublicKey decodePublicKey(byte[] par0ArrayOfByte)
|
||||
{
|
||||
return new ModifiablePublicKey("RSA","X.509",par0ArrayOfByte);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt shared secret AES key using RSA private key
|
||||
*/
|
||||
public static SecretKey decryptSharedKey(PrivateKey par0PrivateKey, byte[] par1ArrayOfByte)
|
||||
{
|
||||
return new SecretKeySpec(decryptData(par0PrivateKey, par1ArrayOfByte), "AES");
|
||||
}
|
||||
|
||||
private static RSA rsa=new RSA(2048);
|
||||
|
||||
/**
|
||||
* Encrypt byte[] data with RSA public key
|
||||
*/
|
||||
public static byte[] encryptData(Key par0Key, byte[] par1ArrayOfByte)
|
||||
{
|
||||
rsa.setPublicKey(new BigInteger(par0Key.getEncoded()));
|
||||
BigInteger res=rsa.encrypt(new BigInteger(par1ArrayOfByte));
|
||||
return res.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt byte[] data with RSA private key
|
||||
*/
|
||||
public static byte[] decryptData(Key par0Key, byte[] par1ArrayOfByte)
|
||||
{
|
||||
rsa.setPrivateKey(new BigInteger(par0Key.getEncoded()));
|
||||
BigInteger res=rsa.decrypt(new BigInteger(par1ArrayOfByte));
|
||||
return res.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new BufferedBlockCipher instance
|
||||
*/
|
||||
public static BufferedBlockCipher createBufferedBlockCipher(boolean par0, Key par1Key)
|
||||
{
|
||||
BufferedBlockCipher var2 = new BufferedBlockCipher(new CFBBlockCipher(new AESFastEngine(), 8));
|
||||
var2.init(par0, new ParametersWithIV(new KeyParameter(par1Key.getEncoded()), par1Key.getEncoded(), 0, 16));
|
||||
return var2;
|
||||
}
|
||||
|
||||
public static OutputStream encryptOuputStream(SecretKey par0SecretKey, OutputStream par1OutputStream)
|
||||
{
|
||||
return new CipherOutputStream(par1OutputStream, createBufferedBlockCipher(true, par0SecretKey));
|
||||
}
|
||||
|
||||
public static InputStream decryptInputStream(SecretKey par0SecretKey, InputStream par1InputStream)
|
||||
{
|
||||
return new CipherInputStream(par1InputStream, createBufferedBlockCipher(false, par0SecretKey));
|
||||
}
|
||||
|
||||
public static OutputStream encryptOuputStream(BufferedBlockCipher bufferedBlockCipher, OutputStream par1OutputStream)
|
||||
{
|
||||
return new CipherOutputStream(par1OutputStream, bufferedBlockCipher);
|
||||
}
|
||||
|
||||
public static InputStream decryptInputStream(BufferedBlockCipher bufferedBlockCipher, InputStream par1InputStream)
|
||||
{
|
||||
return new CipherInputStream(par1InputStream, bufferedBlockCipher);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package me.ayunami2000.ayuncraft;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class ModifiablePublicKey implements PublicKey {
|
||||
private String algorithm;
|
||||
private String format;
|
||||
private byte[] encoded;
|
||||
|
||||
@Override
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return encoded;
|
||||
}
|
||||
|
||||
public ModifiablePublicKey(String algo,String form,byte[] data){
|
||||
algorithm=algo;
|
||||
format=form;
|
||||
encoded=data;
|
||||
}
|
||||
}
|
106
src/teavm/java/me/ayunami2000/ayuncraft/RSA.java
Normal file
106
src/teavm/java/me/ayunami2000/ayuncraft/RSA.java
Normal file
|
@ -0,0 +1,106 @@
|
|||
package me.ayunami2000.ayuncraft;
|
||||
/******************************************************************************
|
||||
* Compilation: javac RSA.java
|
||||
* Execution: java RSA N
|
||||
*
|
||||
* Generate an N-bit public and private RSA key and use to encrypt
|
||||
* and decrypt a random message.
|
||||
*
|
||||
* % java RSA 50
|
||||
* public = 65537
|
||||
* private = 553699199426609
|
||||
* modulus = 825641896390631
|
||||
* message = 48194775244950
|
||||
* encrpyted = 321340212160104
|
||||
* decrypted = 48194775244950
|
||||
*
|
||||
* Known bugs (not addressed for simplicity)
|
||||
* -----------------------------------------
|
||||
* - It could be the case that the message >= modulus. To avoid, use
|
||||
* a do-while loop to generate key until modulus happen to be exactly N bits.
|
||||
*
|
||||
* - It's possible that gcd(phi, publicKey) != 1 in which case
|
||||
* the key generation fails. This will only happen if phi is a
|
||||
* multiple of 65537. To avoid, use a do-while loop to generate
|
||||
* keys until the gcd is 1.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class RSA {
|
||||
private final static BigInteger one = new BigInteger("1");
|
||||
private final static Random random = new Random();
|
||||
|
||||
private BigInteger privateKey;
|
||||
private BigInteger publicKey;
|
||||
private BigInteger modulus;
|
||||
|
||||
// generate an N-bit (roughly) public and private key
|
||||
RSA(int N) {
|
||||
BigInteger p = BigInteger.probablePrime(N/2, random);
|
||||
BigInteger q = BigInteger.probablePrime(N/2, random);
|
||||
BigInteger phi = (p.subtract(one)).multiply(q.subtract(one));
|
||||
|
||||
modulus = p.multiply(q);
|
||||
publicKey = new BigInteger("65537"); // common value in practice = 2^16 + 1
|
||||
privateKey = publicKey.modInverse(phi);
|
||||
}
|
||||
|
||||
|
||||
BigInteger encrypt(BigInteger message) {
|
||||
return message.modPow(publicKey, modulus);
|
||||
}
|
||||
|
||||
BigInteger decrypt(BigInteger encrypted) {
|
||||
return encrypted.modPow(privateKey, modulus);
|
||||
}
|
||||
|
||||
|
||||
void setPublicKey(BigInteger k) {
|
||||
publicKey=k;
|
||||
}
|
||||
|
||||
void setPrivateKey(BigInteger k) {
|
||||
privateKey=k;
|
||||
}
|
||||
|
||||
|
||||
BigInteger getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
BigInteger getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = "";
|
||||
s += "public = " + publicKey + "\n";
|
||||
s += "private = " + privateKey + "\n";
|
||||
s += "modulus = " + modulus;
|
||||
return s;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int N = Integer.parseInt(args[0]);
|
||||
RSA key = new RSA(N);
|
||||
System.out.println(key);
|
||||
|
||||
// create random message, encrypt and decrypt
|
||||
BigInteger message = new BigInteger(N-1, random);
|
||||
|
||||
//// create message by converting string to integer
|
||||
// String s = "test";
|
||||
// byte[] bytes = s.getBytes();
|
||||
// BigInteger message = new BigInteger(bytes);
|
||||
|
||||
BigInteger encrypt = key.encrypt(message);
|
||||
BigInteger decrypt = key.decrypt(encrypt);
|
||||
System.out.println("message = " + message);
|
||||
System.out.println("encrypted = " + encrypt);
|
||||
System.out.println("decrypted = " + decrypt);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user