Skip to content

Commit a8f10b9

Browse files
committed
homomorphic encryption function support && test code
1 parent 5404fe9 commit a8f10b9

3 files changed

Lines changed: 275 additions & 1 deletion

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"sjcl": "~1.0.3",
2323
"web3-core-helpers": "1.0.0-beta.36",
2424
"web3-eth-abi": "1.0.0-beta.36",
25-
"web3-utils": "1.0.0-beta.36"
25+
"web3-utils": "1.0.0-beta.36",
26+
"node-seal": "^4.5.7"
2627
},
2728
"devDependencies": {
2829
"assert-diff": "^1.0.1",

src/index.js

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const Contract = require('./smartContract');
2121
const util = require('./lib/util');
2222
const { utils } = require('elliptic');
2323
const opType = require('./lib/config').opType;
24+
const SEAL = require('node-seal')
25+
2426
const convertStringToHex = util.convertStringToHex;
2527
const getCryptAlgTypeFromAccout = util.getCryptAlgTypeFromAccout;
2628

@@ -1299,7 +1301,221 @@ ChainsqlAPI.prototype.modifySchema = function(schemaInfo){
12991301

13001302
};
13011303

1304+
ChainsqlAPI.prototype.genHomEncryptKeypair= function(encryptParams){
1305+
1306+
return new Promise(function(resolve, reject){
1307+
1308+
let bValid = (encryptParams !== undefined) && (encryptParams.schemeType !== undefined) && (encryptParams.polyModulusDegree !== undefined)
1309+
if(!bValid){
1310+
reject('Invalid parameter')
1311+
}
1312+
1313+
SEAL().then(function(seal){
1314+
1315+
const securityLevel = seal.SecurityLevel.tc128
1316+
const polyModulusDegree = encryptParams.polyModulusDegree
1317+
1318+
var schemeType
1319+
var encryptionParameters
1320+
1321+
1322+
if( encryptParams.schemeType === 'ckks'){
1323+
1324+
schemeType = seal.SchemeType.ckks
1325+
var ckksParms = seal.EncryptionParameters(schemeType)
1326+
ckksParms.setPolyModulusDegree(polyModulusDegree)
1327+
1328+
var maxBitCount = seal.CoeffModulus.MaxBitCount(polyModulusDegree)
1329+
if ( maxBitCount >= 80 ){
1330+
ckksParms.setCoeffModulus(
1331+
seal.CoeffModulus.Create(polyModulusDegree,Int32Array.from([50,30]))
1332+
)
1333+
}else{
1334+
ckksParms.setCoeffModulus(
1335+
seal.CoeffModulus.Create(polyModulusDegree,Int32Array.from([50]))
1336+
)
1337+
}
1338+
1339+
encryptionParameters = ckksParms
1340+
1341+
}else if( encryptParams.schemeType === 'bfv' ) {
1342+
1343+
schemeType = seal.SchemeType.bfv
1344+
var bfvParms = seal.EncryptionParameters(schemeType)
1345+
bfvParms.setPolyModulusDegree(polyModulusDegree)
1346+
1347+
bfvParms.setCoeffModulus(
1348+
seal.CoeffModulus.BFVDefault(polyModulusDegree)
1349+
)
1350+
1351+
bfvParms.setPlainModulus(
1352+
seal.PlainModulus.Batching(polyModulusDegree, 20)
1353+
)
1354+
1355+
encryptionParameters = bfvParms
1356+
1357+
}else{
1358+
reject('Invalid schemeType')
1359+
}
1360+
1361+
const sealContext = seal.Context(
1362+
encryptionParameters, // Encryption Parameters
1363+
true, // ExpandModChain
1364+
securityLevel // Enforce a security level
1365+
)
1366+
1367+
if (!sealContext.parametersSet()) {
1368+
reject(
1369+
'Could not set the parameters in the given context. Please try different encryption parameters.'
1370+
)
1371+
}
1372+
1373+
const keyGenerator = seal.KeyGenerator(sealContext)
1374+
const publicKey = keyGenerator.createPublicKey()
1375+
const secretKey = keyGenerator.secretKey()
1376+
1377+
var homEncryptParams = encryptionParameters.save();
1378+
var homPublicKey = publicKey.save();
1379+
var homPrivateKey = secretKey.save();
1380+
resolve({homEncryptParams,homPublicKey,homPrivateKey})
1381+
}).catch(function(err){
1382+
reject(err);
1383+
});
1384+
1385+
});
1386+
1387+
};
1388+
1389+
1390+
ChainsqlAPI.prototype.homEncrypt= function(encryptParams){
1391+
1392+
return new Promise(function(resolve, reject){
1393+
1394+
let bValid = (encryptParams !== undefined) && (encryptParams.homEncryptParams !== undefined) && (encryptParams.homPublicKey !== undefined)
1395+
&& (encryptParams.homPlainValue !== undefined)
1396+
if(!bValid){
1397+
reject('Invalid parameter')
1398+
}
1399+
1400+
SEAL().then(function(seal){
1401+
1402+
const encryptrParms = seal.EncryptionParameters()
1403+
encryptrParms.load(encryptParams.homEncryptParams)
1404+
1405+
const context = seal.Context(
1406+
encryptrParms, // Encryption Parameters
1407+
true, // ExpandModChain
1408+
seal.SecurityLevel.tc128 // Enforce a security level
1409+
)
1410+
1411+
if (!context.parametersSet()) {
1412+
reject(
1413+
'Could not set the parameters in the given context. Please try different encryption parameters.'
1414+
)
1415+
}
1416+
1417+
var pub = seal.PublicKey();
1418+
pub.load(context,encryptParams.homPublicKey)
1419+
const encryptor = seal.Encryptor(context, pub)
1420+
1421+
var plainText
1422+
var cipherText
1423+
1424+
if ( encryptrParms.scheme === seal.SchemeType.bfv){
1425+
1426+
// bfv模式
1427+
var bfvValue = Number(encryptParams.homPlainValue)
1428+
const array = Int32Array.from([bfvValue])
1429+
const encoder = seal.BatchEncoder(context)
1430+
1431+
plainText = encoder.encode(array)
1432+
cipherText = encryptor.encrypt(plainText)
1433+
1434+
}else if(encryptrParms.scheme === seal.SchemeType.ckks){
1435+
1436+
// ckks 模式
1437+
var ckksValue = Number(encryptParams.homPlainValue)
1438+
var ckksEncoder = seal.CKKSEncoder(context)
1439+
1440+
const arrFloat = Float64Array.from(
1441+
{ length: ckksEncoder.slotCount },
1442+
(_, i) => ckksValue
1443+
)
1444+
1445+
plainText = seal.PlainText()
1446+
ckksEncoder.encode(arrFloat, Math.pow(2, 20), plainText)
1447+
1448+
cipherText = encryptor.encrypt(plainText)
1449+
}
1450+
1451+
resolve( cipherText.save())
1452+
}).catch(function(err){
1453+
reject(err);
1454+
});
1455+
});
1456+
1457+
};
1458+
1459+
ChainsqlAPI.prototype.homDecrypt= function(decryptParams){
1460+
1461+
return new Promise(function(resolve, reject){
1462+
1463+
let bValid = (decryptParams !== undefined) && (decryptParams.homEncryptParams !== undefined) && (decryptParams.homPrivateKey !== undefined)
1464+
&& (decryptParams.homCipherText !== undefined)
1465+
if(!bValid){
1466+
reject('Invalid parameter')
1467+
}
1468+
1469+
SEAL().then(function(seal){
1470+
1471+
const encryptrParms = seal.EncryptionParameters()
1472+
encryptrParms.load(decryptParams.homEncryptParams)
1473+
1474+
const context = seal.Context(
1475+
encryptrParms, // Encryption Parameters
1476+
true, // ExpandModChain
1477+
seal.SecurityLevel.tc128 // Enforce a security level
1478+
)
1479+
1480+
if (!context.parametersSet()) {
1481+
reject(
1482+
'Could not set the parameters in the given context. Please try different encryption parameters.'
1483+
)
1484+
}
13021485

1486+
var secretKey = seal.SecretKey()
1487+
secretKey.load(context,decryptParams.homPrivateKey)
1488+
1489+
const decryptor = seal.Decryptor(context, secretKey)
1490+
1491+
var cipherLoad = seal.CipherText()
1492+
cipherLoad.load(context,decryptParams.homCipherText)
1493+
1494+
// 解密密文
1495+
const plainText = decryptor.decrypt(cipherLoad)
1496+
if ( encryptrParms.scheme === seal.SchemeType.bfv ){
1497+
1498+
// bfv模式
1499+
var bfvEncoder = seal.BatchEncoder(context)
1500+
const decodedArray = bfvEncoder.decode(plainText)
1501+
1502+
resolve(decodedArray[0])
1503+
1504+
}else if(encryptrParms.scheme === seal.SchemeType.ckks){
1505+
1506+
// ckks 模式
1507+
var ckksEncoder = seal.CKKSEncoder(context)
1508+
const decodedArray = ckksEncoder.decode(plainText)
1509+
resolve(decodedArray[0])
1510+
}
1511+
1512+
}).catch(function(err){
1513+
reject(err);
1514+
});
1515+
1516+
});
1517+
1518+
};
13031519

13041520
function callback(data, callback) {
13051521

test/testHE.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Homomorphic Encryption Test Example
2+
const ChainsqlAPI = require('../src/index');
3+
main()
4+
5+
6+
async function main(){
7+
8+
const c = new ChainsqlAPI();
9+
try{
10+
11+
var encyptParms = {
12+
schemeType : 'ckks',
13+
polyModulusDegree : 2048
14+
}
15+
var heKeypair = await c.genHomEncryptKeypair(encyptParms)
16+
17+
var encyptParams = {
18+
homEncryptParams:heKeypair.homEncryptParams,
19+
homPublicKey:heKeypair.homPublicKey,
20+
homPlainValue:'121.00001'
21+
}
22+
var encryptCipher = await c.homEncrypt(encyptParams)
23+
24+
var decryptParams = {
25+
homEncryptParams:heKeypair.homEncryptParams,
26+
homPrivateKey:heKeypair.homPrivateKey,
27+
homCipherText:encryptCipher
28+
}
29+
var plainValue = await c.homDecrypt(decryptParams)
30+
31+
console.log(plainValue)
32+
33+
34+
encyptParms.schemeType = 'bfv'
35+
heKeypair = await c.genHomEncryptKeypair(encyptParms)
36+
//console.log('bfv',JSON.stringify(heKeypair) )
37+
38+
39+
var encyptParams = {
40+
homEncryptParams:heKeypair.homEncryptParams,
41+
homPublicKey:heKeypair.homPublicKey,
42+
homPlainValue:'120'
43+
}
44+
encryptCipher = await c.homEncrypt(encyptParams)
45+
46+
decryptParams = {
47+
homEncryptParams:heKeypair.homEncryptParams,
48+
homPrivateKey:heKeypair.homPrivateKey,
49+
homCipherText:encryptCipher
50+
}
51+
plainValue = await c.homDecrypt(decryptParams)
52+
53+
console.log(plainValue)
54+
}catch(err){
55+
console.error(err)
56+
}
57+
}

0 commit comments

Comments
 (0)