java實(shí)現(xiàn)同態(tài)加密算法的實(shí)例代碼
什么是同態(tài)加密?
同態(tài)加密是上世紀(jì)七十年代就被提出的一個(gè)開(kāi)放問(wèn)題,旨在不暴露數(shù)據(jù)的情況下完成對(duì)數(shù)據(jù)的處理,關(guān)注的是數(shù)據(jù)處理安全。
想象一下這樣一個(gè)場(chǎng)景,作為一名滿懷理想的樓二代,你每天過(guò)著枯燥乏味的收租生活,希望擺脫世俗的枷鎖、銅臭的茍且去追求詩(shī)與遠(yuǎn)方。
你需要雇一個(gè)代理人去承擔(dān)收租的粗活,但又不希望其窺探你每月躺賺的收入。于是,你請(qǐng)高人打造了一套裝備,既能保證代理人順利完成收租,又不會(huì)泄露收入信息。
這套裝備包括信封、膠水、皮夾和神奇剪刀,每一樣?xùn)|西都有奇特的功能:
- 信封一旦用膠水密封,只有神奇剪刀才能拆開(kāi)。
- 不論信封里裝了多少錢(qián),信封的大小和重量都不會(huì)發(fā)生改變。
- 把多個(gè)信封放在皮夾里后,信封會(huì)在不拆開(kāi)的情況下兩兩合并,最后變成一個(gè)信封,里面裝的錢(qián)正好是合并前所有信封金額的總和。

你把信封和膠水分發(fā)給所有租客,把皮夾交給代理人。
到了約定交租的日子,租客把租金放到信封里密封后交給代理人;代理人收齊信封,放到皮夾中,最后得到一個(gè)裝滿所有租金的信封,再轉(zhuǎn)交給你;你使用神奇剪刀拆開(kāi),拿到租金。
在這個(gè)場(chǎng)景中,信封的a、b兩個(gè)性質(zhì)其實(shí)就是公鑰加密的特性,即使用公鑰加密得到的密文只有掌握私鑰的人能夠解密,并且密文不會(huì)泄露明文的語(yǔ)義信息;而c則代表加法同態(tài)的特性,兩個(gè)密文可以進(jìn)行計(jì)算,得到的結(jié)果解密后正好是兩個(gè)原始明文的和。
原理:
paillier加密算法步驟:密鑰生成、加密、解密
1、密鑰生成
1.1 隨機(jī)選擇兩個(gè)大質(zhì)數(shù)p和q滿足gcd(pq,(p-1)(q-1)) =1。這個(gè)屬性保證兩個(gè)質(zhì)數(shù)長(zhǎng)度相等。
1.2 計(jì)算n=pq和λ=lcm(p-1,q-1)
1.3 選擇隨機(jī)整數(shù)g(g ∈ Z n 2 ∗ g∈Z_{n^2}^*g∈Zn2∗),使得滿足n整除g的階。
1.4 公鑰為(N,g)
1.5 私鑰為λ
g c d ( L ( g λ m o d n 2 ) , n ) = 1 gcd(L(g^λ mod n^2),n)=1gcd(L(gλmodn2),n)=1
2、加密
2.1 選擇隨機(jī)數(shù)r ∈ Z n r∈Z_nr∈Zn
2.2 計(jì)算密文
c = E ( m , r ) = g m r n m o d n 2 , r ∈ Z n c = E(m,r) = g^m r^n mod n^2 ,r∈Z_nc=E(m,r)=gmrnmodn2,r∈Zn,其中m為加密信息。
3、解密
m = D ( c , λ ) = ( L ( c λ m o d n 2 ) / L ( g λ m o d n 2 ) ) m o d n , 其 中 L ( u ) = u − 1 / N m= D(c,λ)=(L(c^λ mod n^2)/L(g^λ mod n^2)) mod n,其中 L(u)=u-1/Nm=D(c,λ)=(L(cλmodn2)/L(gλmodn2))modn,其中L(u)=u−1/N
java實(shí)現(xiàn):
package com;
/**
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.math.*;
import java.util.*;
/**
* Paillier Cryptosystem <br>
* <br>
* References: <br>
* [1] Pascal Paillier,
* "Public-Key Cryptosystems Based on Composite Degree Residuosity Classes,"
* EUROCRYPT'99. URL:
* <a rel="external nofollow" >http:
* //www.gemplus.com/smart/rd/publications/pdf/Pai99pai.pdf</a><br>
*
* [2] Paillier cryptosystem from Wikipedia. URL:
* <a rel="external nofollow" >http://en.
* wikipedia.org/wiki/Paillier_cryptosystem</a>
*
* @author Kun Liu (kunliu1@cs.umbc.edu)
* @version 1.0
*/
public class Paillier {
/**
* p and q are two large primes. lambda = lcm(p-1, q-1) =
* (p-1)*(q-1)/gcd(p-1, q-1).
*/
private BigInteger p, q, lambda;
/**
* n = p*q, where p and q are two large primes.
*/
public BigInteger n;
/**
* nsquare = n*n
*/
public BigInteger nsquare;
/**
* a random integer in Z*_{n^2} where gcd (L(g^lambda mod n^2), n) = 1.
*/
private BigInteger g;
/**
* number of bits of modulus
*/
private int bitLength;
/**
* Constructs an instance of the Paillier cryptosystem.
*
* @param bitLengthVal
* number of bits of modulus
* @param certainty
* The probability that the new BigInteger represents a prime
* number will exceed (1 - 2^(-certainty)). The execution time of
* this constructor is proportional to the value of this
* parameter.
*/
public Paillier(int bitLengthVal, int certainty) {
KeyGeneration(bitLengthVal, certainty);
}
/**
* Constructs an instance of the Paillier cryptosystem with 512 bits of
* modulus and at least 1-2^(-64) certainty of primes generation.
*/
public Paillier() {
KeyGeneration(512, 64);
}
/**
* Sets up the public key and private key.
*
* @param bitLengthVal
* number of bits of modulus.
* @param certainty
* The probability that the new BigInteger represents a prime
* number will exceed (1 - 2^(-certainty)). The execution time of
* this constructor is proportional to the value of this
* parameter.
*/
public void KeyGeneration(int bitLengthVal, int certainty) {
bitLength = bitLengthVal;
/*
* Constructs two randomly generated positive BigIntegers that are
* probably prime, with the specified bitLength and certainty.
*/
p = new BigInteger(bitLength / 2, certainty, new Random());
q = new BigInteger(bitLength / 2, certainty, new Random());
n = p.multiply(q);
nsquare = n.multiply(n);
g = new BigInteger("2");
lambda = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE))
.divide(p.subtract(BigInteger.ONE).gcd(q.subtract(BigInteger.ONE)));
/* check whether g is good. */
if (g.modPow(lambda, nsquare).subtract(BigInteger.ONE).divide(n).gcd(n).intValue() != 1) {
System.out.println("g is not good. Choose g again.");
System.exit(1);
}
}
/**
* Encrypts plaintext m. ciphertext c = g^m * r^n mod n^2. This function
* explicitly requires random input r to help with encryption.
*
* @param m
* plaintext as a BigInteger
* @param r
* random plaintext to help with encryption
* @return ciphertext as a BigInteger
*/
public BigInteger Encryption(BigInteger m, BigInteger r) {
return g.modPow(m, nsquare).multiply(r.modPow(n, nsquare)).mod(nsquare);
}
/**
* Encrypts plaintext m. ciphertext c = g^m * r^n mod n^2. This function
* automatically generates random input r (to help with encryption).
*
* @param m
* plaintext as a BigInteger
* @return ciphertext as a BigInteger
*/
public BigInteger Encryption(BigInteger m) {
BigInteger r = new BigInteger(bitLength, new Random());
return g.modPow(m, nsquare).multiply(r.modPow(n, nsquare)).mod(nsquare);
}
/**
* Decrypts ciphertext c. plaintext m = L(c^lambda mod n^2) * u mod n, where
* u = (L(g^lambda mod n^2))^(-1) mod n.
*
* @param c
* ciphertext as a BigInteger
* @return plaintext as a BigInteger
*/
public BigInteger Decryption(BigInteger c) {
BigInteger u = g.modPow(lambda, nsquare).subtract(BigInteger.ONE).divide(n).modInverse(n);
return c.modPow(lambda, nsquare).subtract(BigInteger.ONE).divide(n).multiply(u).mod(n);
}
/**
* sum of (cipher) em1 and em2
*
* @param em1
* @param em2
* @return
*/
public BigInteger cipher_add(BigInteger em1, BigInteger em2) {
return em1.multiply(em2).mod(nsquare);
}
/**
* main function
*
* @param str
* intput string
*/
public static void main(String[] str) {
/* instantiating an object of Paillier cryptosystem */
Paillier paillier = new Paillier();
/* instantiating two plaintext msgs */
BigInteger m1 = new BigInteger("20");
BigInteger m2 = new BigInteger("60");
/* encryption */
BigInteger em1 = paillier.Encryption(m1);
BigInteger em2 = paillier.Encryption(m2);
/* printout encrypted text */
System.out.println(em1);
System.out.println(em2);
/* printout decrypted text */
System.out.println(paillier.Decryption(em1).toString());
System.out.println(paillier.Decryption(em2).toString());
/*
* test homomorphic properties -> D(E(m1)*E(m2) mod n^2) = (m1 + m2) mod
* n
*/
// m1+m2,求明文數(shù)值的和
BigInteger sum_m1m2 = m1.add(m2).mod(paillier.n);
System.out.println("original sum: " + sum_m1m2.toString());
// em1+em2,求密文數(shù)值的乘
BigInteger product_em1em2 = em1.multiply(em2).mod(paillier.nsquare);
System.out.println("encrypted sum: " + product_em1em2.toString());
System.out.println("decrypted sum: " + paillier.Decryption(product_em1em2).toString());
/* test homomorphic properties -> D(E(m1)^m2 mod n^2) = (m1*m2) mod n */
// m1*m2,求明文數(shù)值的乘
BigInteger prod_m1m2 = m1.multiply(m2).mod(paillier.n);
System.out.println("original product: " + prod_m1m2.toString());
// em1的m2次方,再mod paillier.nsquare
BigInteger expo_em1m2 = em1.modPow(m2, paillier.nsquare);
System.out.println("encrypted product: " + expo_em1m2.toString());
System.out.println("decrypted product: " + paillier.Decryption(expo_em1m2).toString());
//sum test
System.out.println("--------------------------------");
Paillier p = new Paillier();
BigInteger t1 = new BigInteger("21");System.out.println(t1.toString());
BigInteger t2 = new BigInteger("50");System.out.println(t2.toString());
BigInteger t3 = new BigInteger("50");System.out.println(t3.toString());
BigInteger et1 = p.Encryption(t1);System.out.println(et1.toString());
BigInteger et2 = p.Encryption(t2);System.out.println(et2.toString());
BigInteger et3 = p.Encryption(t3);System.out.println(et3.toString());
BigInteger sum = new BigInteger("1");
sum = p.cipher_add(sum, et1);
sum = p.cipher_add(sum, et2);
sum = p.cipher_add(sum, et3);
System.out.println("sum: "+sum.toString());
System.out.println("decrypted sum: "+p.Decryption(sum).toString());
System.out.println("--------------------------------");
}
}
參考:https://mp.weixin.qq.com/s?__biz=MzA3MTI5Njg4Mw==&mid=2247486135&idx=1&sn=8c9431012aef19bbdefdcd673a783c34&chksm=9f2ef8aba85971bdfb623e8303b103fd70ac2a5ad802668388233ca930d1b0cd77fb02d4b0f2&scene=21#wechat_redirect
https://www.csee.umbc.edu/~kunliu1/research/Paillier.html
總結(jié)
到此這篇關(guān)于java實(shí)現(xiàn)同態(tài)加密算法的文章就介紹到這了,更多相關(guān)java同態(tài)加密算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java實(shí)現(xiàn)雪花算法的原理
- Java實(shí)現(xiàn)雪花算法(snowflake)
- java遞歸實(shí)現(xiàn)科赫雪花
- java分形繪制科赫雪花曲線(科赫曲線)代碼分享
- Java數(shù)據(jù)結(jié)構(gòu)與算法入門(mén)實(shí)例詳解
- Java算法之?dāng)?shù)組冒泡排序代碼實(shí)例講解
- 使用java寫(xiě)的矩陣乘法實(shí)例(Strassen算法)
- java中g(shù)c算法實(shí)例用法
- java實(shí)現(xiàn)國(guó)產(chǎn)sm4加密算法
- java算法之靜態(tài)內(nèi)部類(lèi)實(shí)現(xiàn)雪花算法
相關(guān)文章
Java中Object類(lèi)常用的12個(gè)方法(小結(jié))
Java 中的 Object 方法在面試中是一個(gè)非常高頻的點(diǎn),本文主要介紹了Java中Object類(lèi)常用的12個(gè)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12
Java利用多線程模擬銀行系統(tǒng)存錢(qián)問(wèn)題
本文將利用Java多線程模擬銀行系統(tǒng)存錢(qián)問(wèn)題:使用兩個(gè)不同的線程向同一個(gè)賬戶存錢(qián)。文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-08-08
使用spring oauth2框架獲取當(dāng)前登錄用戶信息的實(shí)現(xiàn)代碼
這篇文章主要介紹了使用spring oauth2框架獲取當(dāng)前登錄用戶信息的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
Java面向?qū)ο蟪绦蛟O(shè)計(jì)多態(tài)性示例
這篇文章主要介紹了Java面向?qū)ο蟪绦蛟O(shè)計(jì)多態(tài)性,結(jié)合實(shí)例形式分析了java多態(tài)性的概念、原理、定義與使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下2018-03-03
Java 實(shí)戰(zhàn)項(xiàng)目之精美物流管理系統(tǒng)的實(shí)現(xiàn)流程
讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SpringBoot+Vue+maven+Mysql實(shí)現(xiàn)一個(gè)精美的物流管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-11-11
Mybatis-Plus最優(yōu)化持久層開(kāi)發(fā)過(guò)程
Mybatis-plus(簡(jiǎn)稱(chēng)MP)是一個(gè)Mybatis的增強(qiáng)工具,在mybatis的基礎(chǔ)上只做增強(qiáng)不做改變,提高效率,自動(dòng)生成單表的CRUD功能,這篇文章主要介紹了Mybatis-Plus最優(yōu)化持久層開(kāi)發(fā),需要的朋友可以參考下2024-07-07
Mybatis批量插入Oracle數(shù)據(jù)的方法實(shí)例
在開(kāi)發(fā)中或多或少都會(huì)遇到數(shù)據(jù)批量插入的功能,最近我在做項(xiàng)目的過(guò)程中就遇到了這樣一個(gè)問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Mybatis批量插入Oracle數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2022-01-01
java實(shí)現(xiàn)圖片角度旋轉(zhuǎn)并獲得圖片信息
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)圖片角度旋轉(zhuǎn)并獲得圖片信息,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02

