make Trypt cryptographically secure (i believe)
This commit is contained in:
parent
01097353b7
commit
c98ab6de76
3 changed files with 87 additions and 27 deletions
|
@ -61,11 +61,10 @@ public class ChatCrypt extends Feature {
|
||||||
public boolean useTrypt = false;
|
public boolean useTrypt = false;
|
||||||
|
|
||||||
@Config("Seed")
|
@Config("Seed")
|
||||||
@Description("(Must be a number or will be hashed into one.)\n" +
|
@Description("PRNG seed to make results less predictable.\n" +
|
||||||
"PRNG seed to make results less predictable.\n" +
|
|
||||||
"On SBE: Necessary for decreasing the likelihood of undigested bytes.\n" +
|
"On SBE: Necessary for decreasing the likelihood of undigested bytes.\n" +
|
||||||
"On Trypt: Necessary for scrambling byte order and decreasing the likelihood of undigested bytes.")
|
"On Trypt: Necessary for scrambling byte order and decreasing the likelihood of undigested bytes.")
|
||||||
public String sSeed = "94278";
|
public String sSeed = "this is a bad seed";
|
||||||
|
|
||||||
@Config("Box Size")
|
@Config("Box Size")
|
||||||
@Description("The size of the SBE random data box.")
|
@Description("The size of the SBE random data box.")
|
||||||
|
@ -116,15 +115,15 @@ public class ChatCrypt extends Feature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int seed = -1;
|
int iSeed = -1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEveryTick() {
|
public void onEveryTick() {
|
||||||
useTrypt = !useSBE;
|
useTrypt = !useSBE;
|
||||||
try {
|
try {
|
||||||
seed = Integer.parseInt(sSeed);
|
iSeed = Integer.parseInt(sSeed);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
seed = sSeed.hashCode();
|
iSeed = sSeed.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,12 +222,12 @@ public class ChatCrypt extends Feature {
|
||||||
|
|
||||||
public String encrypt(String value) {
|
public String encrypt(String value) {
|
||||||
if(useSBE) {
|
if(useSBE) {
|
||||||
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
|
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, iSeed);
|
||||||
return armorBytes(sbe.transform(value.getBytes(StandardCharsets.UTF_8)));
|
return armorBytes(sbe.transform(value.getBytes(StandardCharsets.UTF_8)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(!keepTrypt || trypt == null)
|
if(!keepTrypt || trypt == null)
|
||||||
trypt = new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), scramble);
|
trypt = new Trypt(sSeed.getBytes(StandardCharsets.UTF_8), Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), scramble);
|
||||||
return armorBytes(trypt.encryptChunk(value.getBytes(StandardCharsets.UTF_8)));
|
return armorBytes(trypt.encryptChunk(value.getBytes(StandardCharsets.UTF_8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,32 +235,32 @@ public class ChatCrypt extends Feature {
|
||||||
|
|
||||||
public String decrypt(byte[] encrypted) {
|
public String decrypt(byte[] encrypted) {
|
||||||
if(useSBE) {
|
if(useSBE) {
|
||||||
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
|
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, iSeed);
|
||||||
return new String(sbe.transform(encrypted), StandardCharsets.US_ASCII);
|
return new String(sbe.transform(encrypted), StandardCharsets.US_ASCII);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(!keepTrypt || trypt == null)
|
if(!keepTrypt || trypt == null)
|
||||||
trypt = new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), scramble);
|
trypt = new Trypt(sSeed.getBytes(StandardCharsets.UTF_8), Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), scramble);
|
||||||
return new String(trypt.decryptChunk(encrypted), StandardCharsets.UTF_8);
|
return new String(trypt.decryptChunk(encrypted), StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String encryptNoKeep(String value) {
|
public String encryptNoKeep(String value) {
|
||||||
if (useSBE) {
|
if (useSBE) {
|
||||||
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
|
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, iSeed);
|
||||||
return armorBytes(sbe.transform(value.getBytes(StandardCharsets.UTF_8)));
|
return armorBytes(sbe.transform(value.getBytes(StandardCharsets.UTF_8)));
|
||||||
} else {
|
} else {
|
||||||
return armorBytes(new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), 0).encryptChunk(value.getBytes(StandardCharsets.UTF_8)));
|
return armorBytes(new Trypt(sSeed.getBytes(StandardCharsets.UTF_8), Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), 0).encryptChunk(value.getBytes(StandardCharsets.UTF_8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String decryptNoKeep(byte[] encrypted) {
|
public String decryptNoKeep(byte[] encrypted) {
|
||||||
if(useSBE) {
|
if(useSBE) {
|
||||||
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, seed);
|
SBE sbe = new SBE(Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), boxSize, iSeed);
|
||||||
return new String(sbe.transform(encrypted), StandardCharsets.US_ASCII);
|
return new String(sbe.transform(encrypted), StandardCharsets.US_ASCII);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new String(new Trypt(seed, Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), 0).decryptChunk(encrypted), StandardCharsets.UTF_8);
|
return new String(new Trypt(sSeed.getBytes(StandardCharsets.UTF_8), Hasher.sha512hex(password).getBytes(StandardCharsets.UTF_8), 0).decryptChunk(encrypted), StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.baseband.client.util.misc;
|
||||||
|
|
||||||
|
import de.tudbut.obj.NotSupportedException;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class SecurePRandom extends Random {
|
||||||
|
|
||||||
|
private final MessageDigest sha256;
|
||||||
|
private final byte[] seed;
|
||||||
|
private long index = 0;
|
||||||
|
|
||||||
|
public SecurePRandom(byte[] seed) {
|
||||||
|
super(0);
|
||||||
|
this.seed = seed;
|
||||||
|
try {
|
||||||
|
sha256 = MessageDigest.getInstance("SHA-256");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new NotSupportedException("SecurePRandom is not supported on this JVM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void setSeed(long seed) {
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized byte[] nextBytes() {
|
||||||
|
sha256.reset();
|
||||||
|
sha256.update(seed);
|
||||||
|
byte[] bytes = new byte[8];
|
||||||
|
bytes[0] = (byte) (index >> 56 & 0xff);
|
||||||
|
bytes[1] = (byte) (index >> 48 & 0xff);
|
||||||
|
bytes[2] = (byte) (index >> 40 & 0xff);
|
||||||
|
bytes[3] = (byte) (index >> 32 & 0xff);
|
||||||
|
bytes[4] = (byte) (index >> 24 & 0xff);
|
||||||
|
bytes[5] = (byte) (index >> 16 & 0xff);
|
||||||
|
bytes[6] = (byte) (index >> 8 & 0xff);
|
||||||
|
bytes[7] = (byte) (index >> 0 & 0xff);
|
||||||
|
index++;
|
||||||
|
return sha256.digest(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void nextBytes(byte[] bytes) {
|
||||||
|
for(int i = 0; i < bytes.length; i += 32) {
|
||||||
|
System.arraycopy(nextBytes(), 0, bytes, i, Math.min(32, bytes.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
final protected int next(int numBits) {
|
||||||
|
int numBytes = (numBits+7)/8;
|
||||||
|
byte[] b = new byte[numBytes];
|
||||||
|
int next = 0;
|
||||||
|
|
||||||
|
nextBytes(b);
|
||||||
|
for (int i = 0; i < numBytes; i++) {
|
||||||
|
next = (next << 8) + (b[i] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next >>> (numBytes*8 - numBits);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,20 +2,17 @@ package com.baseband.client.util.misc;
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class Trypt {
|
public class Trypt {
|
||||||
private final SecureRandom sRand = new SecureRandom();
|
private final SecureRandom sRand = new SecureRandom();
|
||||||
private final Random cRandE;
|
private final SecurePRandom cRandE;
|
||||||
private final Random cRandD;
|
private final SecurePRandom cRandD;
|
||||||
private final long seed;
|
|
||||||
private final byte[] key;
|
private final byte[] key;
|
||||||
private final int scramble;
|
private final int scramble;
|
||||||
|
|
||||||
public Trypt(long seed, byte[] key, int scramble) {
|
public Trypt(byte[] seed, byte[] key, int scramble) {
|
||||||
cRandE = new Random(seed);
|
cRandE = new SecurePRandom(seed);
|
||||||
cRandD = new Random(seed);
|
cRandD = new SecurePRandom(seed);
|
||||||
this.seed = seed;
|
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.scramble = scramble;
|
this.scramble = scramble;
|
||||||
}
|
}
|
||||||
|
@ -29,18 +26,17 @@ public class Trypt {
|
||||||
for (byte b : input) {
|
for (byte b : input) {
|
||||||
data.add(b);
|
data.add(b);
|
||||||
}
|
}
|
||||||
ArrayList<Integer> forbidden = new ArrayList<>(input.length);
|
ArrayList<Integer> finished = new ArrayList<>(input.length);
|
||||||
byte[] output = new byte[input.length + 1];
|
byte[] output = new byte[input.length + 1];
|
||||||
output[0] = salt;
|
output[0] = salt;
|
||||||
|
|
||||||
for(int i = 0; i < input.length;) {
|
for(int i = 0; i < input.length;) {
|
||||||
int newLocation = cRandE.nextInt(input.length);
|
int newLocation = cRandE.nextInt(input.length);
|
||||||
if(forbidden.contains(newLocation))
|
if(finished.contains(newLocation))
|
||||||
continue;
|
continue;
|
||||||
forbidden.add(newLocation);
|
finished.add(newLocation);
|
||||||
byte old = data.remove(0);
|
byte old = data.remove(0);
|
||||||
output[newLocation + 1] = (byte) (old ^ salt ^ key[(i++ ^ cRandE.nextInt(0x7fffffff)) % key.length]);
|
output[newLocation + 1] = (byte) (old ^ salt ^ key[(i++ ^ cRandE.nextInt(0x7fffffff)) % key.length]);
|
||||||
salt = (byte) (salt ^ (newLocation << cRandE.nextInt(8)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (byte b = 0; b < input[cRandE.nextInt(input.length)]; b++) {
|
for (byte b = 0; b < input[cRandE.nextInt(input.length)]; b++) {
|
||||||
|
@ -62,7 +58,6 @@ public class Trypt {
|
||||||
forbidden.add(newLocation);
|
forbidden.add(newLocation);
|
||||||
byte encrypted = input[newLocation + 1];
|
byte encrypted = input[newLocation + 1];
|
||||||
output[i] = (byte) (encrypted ^ salt ^ key[(i++ ^ cRandD.nextInt(0x7fffffff)) % key.length]);
|
output[i] = (byte) (encrypted ^ salt ^ key[(i++ ^ cRandD.nextInt(0x7fffffff)) % key.length]);
|
||||||
salt = (byte) (salt ^ (newLocation << cRandD.nextInt(8)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (byte b = 0; b < output[cRandD.nextInt(output.length)]; b++) {
|
for (byte b = 0; b < output[cRandD.nextInt(output.length)]; b++) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue