java實現(xiàn)同態(tài)加密算法的實例代碼
什么是同態(tài)加密?
同態(tài)加密是上世紀(jì)七十年代就被提出的一個開放問題,旨在不暴露數(shù)據(jù)的情況下完成對數(shù)據(jù)的處理,關(guān)注的是數(shù)據(jù)處理安全。
想象一下這樣一個場景,作為一名滿懷理想的樓二代,你每天過著枯燥乏味的收租生活,希望擺脫世俗的枷鎖、銅臭的茍且去追求詩與遠(yuǎn)方。
你需要雇一個代理人去承擔(dān)收租的粗活,但又不希望其窺探你每月躺賺的收入。于是,你請高人打造了一套裝備,既能保證代理人順利完成收租,又不會泄露收入信息。
這套裝備包括信封、膠水、皮夾和神奇剪刀,每一樣?xùn)|西都有奇特的功能:
- 信封一旦用膠水密封,只有神奇剪刀才能拆開。
- 不論信封里裝了多少錢,信封的大小和重量都不會發(fā)生改變。
- 把多個信封放在皮夾里后,信封會在不拆開的情況下兩兩合并,最后變成一個信封,里面裝的錢正好是合并前所有信封金額的總和。
你把信封和膠水分發(fā)給所有租客,把皮夾交給代理人。
到了約定交租的日子,租客把租金放到信封里密封后交給代理人;代理人收齊信封,放到皮夾中,最后得到一個裝滿所有租金的信封,再轉(zhuǎn)交給你;你使用神奇剪刀拆開,拿到租金。
在這個場景中,信封的a、b兩個性質(zhì)其實就是公鑰加密的特性,即使用公鑰加密得到的密文只有掌握私鑰的人能夠解密,并且密文不會泄露明文的語義信息;而c則代表加法同態(tài)的特性,兩個密文可以進(jìn)行計算,得到的結(jié)果解密后正好是兩個原始明文的和。
原理:
paillier加密算法步驟:密鑰生成、加密、解密
1、密鑰生成
1.1 隨機選擇兩個大質(zhì)數(shù)p和q滿足gcd(pq,(p-1)(q-1)) =1。這個屬性保證兩個質(zhì)數(shù)長度相等。
1.2 計算n=pq和λ=lcm(p-1,q-1)
1.3 選擇隨機整數(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 選擇隨機數(shù)r ∈ Z n r∈Z_nr∈Zn
2.2 計算密文
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實現(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實現(xiàn)同態(tài)加密算法的文章就介紹到這了,更多相關(guān)java同態(tài)加密算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot+vue實現(xiàn)阿里云oss大文件分片上傳的示例代碼
阿里云推出了直傳,本文主要介紹了springboot+vue實現(xiàn)阿里云oss大文件分片上傳的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06Java并發(fā)編程之synchronized底層實現(xiàn)原理分析
這篇文章主要介紹了Java并發(fā)編程之synchronized底層實現(xiàn)原理,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02rabbitmq學(xué)習(xí)系列教程之消息應(yīng)答(autoAck)、隊列持久化(durable)及消息持久化
這篇文章主要介紹了rabbitmq學(xué)習(xí)系列教程之消息應(yīng)答(autoAck)、隊列持久化(durable)及消息持久化,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03