Paillier同态加密算法 java实现
同态加密 密码学 数据结构 java
·
import org.jetbrains.annotations.NotNull;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Random;
public class Painkiller {
public BigInteger P,Q;
public BigInteger N;
public BigInteger NSQ;
public BigInteger lamda;
public int bitLength;
public BigInteger g;
public BigInteger u;
public Painkiller(){
Key(64,64);
}
public Painkiller(int bitLength,int certainty){
Key(bitLength,certainty);
}
public Painkiller(BigInteger N,BigInteger lamda,int bitLength,BigInteger u){
this.N=N;
this.lamda=lamda;
this.bitLength=bitLength;
this.u=u;
}
public void Key(int bitLengthVal, int certainty) {
bitLength = bitLengthVal;
this.P = new BigInteger(bitLength / 2, certainty, new Random());
this.Q = new BigInteger(bitLength / 2, certainty, new Random());
this.N = P.multiply(Q);
this.NSQ = N.multiply(N);
this.g = N.add(new BigInteger("1"));
this.lamda = P.subtract(BigInteger.ONE).multiply(Q.subtract(BigInteger.ONE))
.divide(P.subtract(BigInteger.ONE).gcd(Q.subtract(BigInteger.ONE)));
this.u = g.modPow(this.lamda, this.NSQ).subtract(BigInteger.ONE).divide(this.N).modInverse(this.N);
if (this.g.modPow(this.lamda, this.NSQ).subtract(BigInteger.ONE).divide(this.N).gcd(this.N).intValue() != 1) {
System.out.println("g的选取不合适!");
System.exit(1);
}
}
public BigInteger En(BigInteger m, @NotNull BigInteger r) {
return g.modPow(m, this.NSQ).multiply(r.modPow(this.N, this.NSQ)).mod(this.NSQ);
}
public BigInteger En(BigInteger m) {
BigInteger r = new BigInteger(bitLength, new Random());
// System.out.println("random:"+r);
// System.out.println(("g.modPow(m,NSQ:")+g.modPow(m,this.NSQ));
// System.out.println("g.modPow(m,NSQ).mul(r.modPow(N,NSQ)):"+g.modPow(m,this.NSQ).multiply(r.modPow(this.N,this.NSQ)));
return g.modPow(m, this.NSQ).multiply(r.modPow(this.N, this.NSQ)).mod(this.NSQ);
}
public BigInteger De(@NotNull BigInteger c) {
return c.modPow(this.lamda, this.NSQ).subtract(BigInteger.ONE).divide(this.N).multiply(this.u).mod(this.N);
}
public BigInteger En(@NotNull String message){
String encoded = Base64.getEncoder().encodeToString(message.getBytes());
byte []encoded_b = encoded.getBytes(StandardCharsets.UTF_8);
StringBuilder message_b = new StringBuilder();
for(byte val:encoded_b){
// System.out.printf("%03d",val);
message_b.append(String.format("%03d", val));
}
return this.En(new BigInteger(String.valueOf(message_b)));
}
public String DeIfEnByString(BigInteger c){
c = De(c);
BigInteger md = new BigInteger("1000");
System.out.println(c.toString().length());
byte []bigIntToByteArr = new byte[(c.toString().length()/3+(c.toString().length()%3==0?0:1))];
System.out.println(bigIntToByteArr.length);
for(int i=0;i<bigIntToByteArr.length;i++){
BigInteger val=c.mod(md);
bigIntToByteArr[bigIntToByteArr.length-1-i]=Byte.parseByte(String.valueOf(val));
c = c.divide(md);
}
// System.out.println("DeIfEnByString:"+ Arrays.toString(bigIntToByteArr));
// System.out.println(new String(Base64.getDecoder().decode(new String(bigIntToByteArr))));
// return new String("");
return new String(Base64.getDecoder().decode(new String(bigIntToByteArr)));
}
public void showKeys(){
System.out.println("bitLength:"+this.bitLength);
System.out.println("Public Key:\nN:"+this.N+"\ng:"+this.g);
System.out.println("Private Key:\nlamda:"+this.lamda+"\nu:"+this.u);
}
public static void main(String[] args) {
Painkiller pkr = new Painkiller(64,32);
pkr.showKeys();
BigInteger crypto = pkr.En(new BigInteger("114514"));
BigInteger message = pkr.De(crypto);
System.out.println("crypto:"+crypto);
System.out.println("message:"+message);
// System.out.println(pkr.De(pkr.En(new BigInteger("11").add(new BigInteger("2"))).mod(pkr.NSQ)));
// System.out.println(new BigInteger("123456789109876654321").modPow(new BigInteger("114514415411"),new BigInteger("123456789112409876654321")));
}
}
// Painkiller pkr = new Painkiller();
// pkr.P=new BigInteger("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")
// Painkiller pkr = new Painkiller(128,32);
// BigInteger message = new BigInteger("12345678901234567890123456789012");
// System.out.println(message);
// System.out.println(pkr.En(message));
// System.out.println(pkr.De(pkr.En(message)));
// BigInteger bn = pkr.De(pkr.En(str));
// System.out.println("bn"+bn);
// BigInteger md = new BigInteger("1000");
// byte []bigIntToByteArr = new byte[(bn.toString().length()/3+(bn.toString().length()%3==0?0:1))];
// for(int i=0;i<bigIntToByteArr.length;i++){
// BigInteger val=bn.mod(md);
// System.out.print(val+" ");
// bigIntToByteArr[bigIntToByteArr.length-1-i]=Byte.parseByte(String.valueOf(val));
// bn = bn.divide(md);
// }
// System.out.println();
// System.out.println(Arrays.toString(bigIntToByteArr));
// for(byte key:bigIntToByteArr){
// System.out.printf("%s",String.valueOf((char)key));
// }
// System.out.println();
// System.out.println(new String(bigIntToByteArr));
// byte[] decoded = Base64.getDecoder().decode(encoded);
// System.out.println("Base64解码:"+new String(decoded));
// System.out.println(new String(Base64.getDecoder().decode(new String(bigIntToByteArr))));
// String encoded = Base64.getEncoder().encodeToString(str.getBytes());
// System.out.println("Base64编码:"+encoded);
// System.out.println(pkr.En(str));
// System.out.println(pkr.En(str));
// System.out.println(Arrays.toString(encoded.getBytes(StandardCharsets.UTF_8)));
// byte []encoded_b = encoded.getBytes(StandardCharsets.UTF_8);
// System.out.println(pkr.De(pkr.En(str)));
// System.out.println(Arrays.toString(encoded_b));
// pkr.DeIfEnByString(pkr.En(str));
更多推荐
所有评论(0)