/* * Copyright (c) 2012-2020 MIRACL UK Ltd. * * This file is part of MIRACL Core * (see https://github.com/miracl/core). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Kyber API */ package core //import "fmt" const KY_LGN uint = 8 const KY_DEGREE int = (1 << KY_LGN); const KY_PRIME int32 = 0xD01 const KY_ONE int32 = 0x549 // R mod Q const KY_QINV int32 = 62209 // q^(-1) mod 2^16 const KYBER_SECRET_CPA_SIZE_512 int = (2*(KY_DEGREE*3)/2) const KYBER_PUBLIC_SIZE_512 int = (32+2*(KY_DEGREE*3)/2) const KYBER_CIPHERTEXT_SIZE_512 int = ((10*2+4)*KY_DEGREE/8) const KYBER_SECRET_CCA_SIZE_512 int = (KYBER_SECRET_CPA_SIZE_512+KYBER_PUBLIC_SIZE_512+64) const KYBER_SHARED_SECRET_512 int = 32 const KYBER_SECRET_CPA_SIZE_768 int = (3*(KY_DEGREE*3)/2) const KYBER_PUBLIC_SIZE_768 int = (32+3*(KY_DEGREE*3)/2) const KYBER_CIPHERTEXT_SIZE_768 int = ((10*3+4)*KY_DEGREE/8) const KYBER_SECRET_CCA_SIZE_768 int = (KYBER_SECRET_CPA_SIZE_768+KYBER_PUBLIC_SIZE_768+64) const KYBER_SHARED_SECRET_768 int = 32 const KYBER_SECRET_CPA_SIZE_1024 int = (4*(KY_DEGREE*3)/2) const KYBER_PUBLIC_SIZE_1024 int = (32+4*(KY_DEGREE*3)/2) const KYBER_CIPHERTEXT_SIZE_1024 int = ((11*4+5)*KY_DEGREE/8) const KYBER_SECRET_CCA_SIZE_1024 int = (KYBER_SECRET_CPA_SIZE_1024+KYBER_PUBLIC_SIZE_1024+64) const KYBER_SHARED_SECRET_1024 int = 32 const KY_MAXK = 4; // parameters for each security level // K,eta1,eta2,du,dv,shared secret var PARAMS_512 = [6]int{2,3,2,10,4,32} var PARAMS_768 = [6]int{3,2,2,10,4,32} var PARAMS_1024 = [6]int{4,2,2,11,5,32} /* Translated from public domain reference implementation code - taken from https://github.com/pq-crystals/kyber */ var ZETAS = [256]int16{ -1044, -758, -359, -1517, 1493, 1422, 287, 202, -171, 622, 1577, 182, 962, -1202, -1474, 1468, 573, -1325, 264, 383, -829, 1458, -1602, -130, -681, 1017, 732, 608, -1542, 411, -205, -1571, 1223, 652, -552, 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666, -1618, -1162, 126, 1469, -853, -90, -271, 830, 107, -1421, -247, -951, -398, 961, -1508, -725, 448, -1065, 677, -1275, -1103, 430, 555, 843, -1251, 871, 1550, 105, 422, 587, 177, -235, -291, -460, 1574, 1653, -246, 778, 1159, -147, -777, 1483, -602, 1119, -1590, 644, -872, 349, 418, 329, -156, -75, 817, 1097, 603, 610, 1322, -1285, -1465, 384, -1215, -136, 1218, -1335, -874, 220, -1187, -1659, -1185, -1530, -1278, 794, -1510, -854, -870, 478, -108, -308, 996, 991, 958, -1460, 1522, 1628} func montgomery_reduce(a int32) int16 { t := int16(a*KY_QINV) t = int16((a - int32(t)*KY_PRIME) >> 16) return t } func barrett_reduce(a int16) int16 { v := int16(((int32(1)<<26) + KY_PRIME/2)/KY_PRIME) vv := int32(v) aa := int32(a) t := int16((vv*aa + 0x2000000) >> 26); t *= int16(KY_PRIME) return int16(a - t); } func fqmul(a int16, b int16) int16 { return montgomery_reduce(int32(a)*int32(b)); } func ntt(r []int16) { var j int k := 1 for len := 128; len >= 2; len >>= 1 { for start := 0; start < 256; start = j + len { zeta := ZETAS[k]; k+=1 for j = start; j < start + len; j++ { t := fqmul(zeta, r[j + len]) r[j + len] = r[j] - t r[j] = r[j] + t } } } } func invntt(r []int16) { var j int f := int16(1441) // mont^2/128 k := 127 for len := 2; len <= 128; len <<= 1 { for start := 0; start < 256; start = j + len { zeta := ZETAS[k]; k-=1 for j = start; j < start + len; j++ { t := r[j] r[j] = barrett_reduce(t + r[j + len]) r[j + len] = (r[j + len] - t) r[j + len] = fqmul(zeta, r[j + len]) } } } for j := 0; j < 256; j++ { r[j] = fqmul(r[j], f) } } func basemul(index int,r []int16, a []int16, b []int16,zeta int16) { i:=index j:=index+1 r[i] = fqmul(a[j], b[j]) r[i] = fqmul(r[i], zeta) r[i] += fqmul(a[i], b[i]) r[j] = fqmul(a[i], b[j]) r[j] += fqmul(a[j], b[i]) } func poly_reduce(r []int16) { for i:=0;i>bt)&1) } // centered binomial distribution func cbd(bts []byte,eta int,f []int16) { for i:=0;i>bts) mask:=int16((1<=8{ bts-=8 ptr++ } w:=int16(r&mask) position[0]=ptr position[1]=bts return w } // array t has ab active bits per word // extract bytes from array of words // if max!=0 then -max<=t[i]<=+max func nextbyte16(ab int,t []int16,position []int) byte { ptr:=position[0] // index in array bts:=position[1] // bit index in byte left:=ab-bts // number of bits left in this word i:=0 k:=ptr%256 w:=t[k]; w+=(w>>15)&int16(KY_PRIME) r:=int16(w>>bts); for left<8 { i++ w=t[k+i]; w+=(w>>15)&int16(KY_PRIME) r|=w<=ab { bts-=ab; ptr++; } position[0]=ptr position[1]=bts return byte(r&0xff); } // encode polynomial vector of length len with coefficients of length L, into packed bytes func encode(t []int16,pos []int,L int,pack []byte,pptr int) { k:=(KY_DEGREE*L)/8 // compressed length for n:=0;n>15)&int16(KY_PRIME) t[i]= int16(((twod*int32(t[i])+KY_PRIME/2)/KY_PRIME)&(twod-1)) } } // decompress polynomial coefficents in place, for polynomial vector of length len func decompress(t []int16,d int) { twod1:=int32(1<<(d-1)) for i:=0;i>d) } } // input entropy, output key pair func cpa_keypair(params [6]int,tau []byte,sk []byte,pk []byte) { sh := NewSHA3(SHA3_HASH512) var rho [32]byte var sigma [33]byte var buff [256]byte ck:=params[0] var r [KY_DEGREE]int16 var w [KY_DEGREE]int16 var Aij [KY_DEGREE]int16 var s= make([][KY_DEGREE]int16, ck) var e= make([][KY_DEGREE]int16, ck) var p= make([][KY_DEGREE]int16, ck) eta1:=params[1] public_key_size:=32+ck*(KY_DEGREE*3)/2 // secret_cpa_key_size:=ck*(KY_DEGREE*3)/2 for i:=0;i<32;i++ { sh.Process(tau[i]) } bf := sh.Hash(); for i:=0;i<32;i++ { rho[i]=bf[i] sigma[i]=bf[i+32] } sigma[32]=0 // N // create s for i:=0;i