在介绍NTRU之前,我需要学习一些格的知识,点击查看。
格的基本知识
在离散数学中格的定义:格是其非空有限有限子集都有一个上确界和下确界的偏序集合。
偏序集合:(英语:Partially ordered set,简写poset)是数学中,特别是序理论中,指配备了部分排序关系的集合。 这个理论将排序、顺序或排列这个集合的元素的直觉概念抽象化。这种排序不必然需要是全部的,就是说不必要保证此集合内的所有对象的相互可比较性。部分排序集合定义了部分排拓扑。
线性无关:
NTRU
NTRU是一个带有专利保护的开源公开密钥加密系统,使用基于格的加密算法来加密数据。它包括两部分算法:NTRUEncrypt用来加密,NTRUSign用来进行数字签名。与其他流行的公钥加密系统不同,它可以防止被Shor算法破解,并显著提升了性能。NTRU算法被认为可以抵抗量子攻击。
NTRU is based on the SVP or CVP in a lattice
算法流程如下:
文字描述如下:
详细介绍参考百度文库文章。
例子
这个例子计算需要用到center lift这个概念的内容。介绍在最后。
center lift
例子,其实很简单就是取[-q/2,q/2]的数和a_i模q同余的代替即可。
代码例题
实现如下参数的NTRU算法
(N, p, q) = (7, 2, 29),Alice的公钥为
Bob希望发送明文消息
,
1)输出Bob发送的密文
2)
2)。用私钥解密1)中所得的密文,验证是否等于明文。
package main
import "fmt"
var N int = 7 //参数N
var P int = 2 //参数P
var Q int = 29 //参数Q
var poly_h = [7]int{23, 23, 23, 24, 23, 24, 23} //公钥
var poly_f = [7]int{1, 1, 1, 0, 1, 1, 0}
var poly_f_P = [7]int{1, 0, 0, 0, 0, 1, 1} //和poly_f组成私钥
var poly_m = [7]int{3, 0, 3, 0, 0, 0, 0} //明文
var poly_r = [7]int{1, 1, 0, 1, 0, 0, 1} //随机秘钥
var temp_r [7]int //存储P*r(x)的值
var poly_cipher map[int]int //存储加密密文,temp_r(x)*poly_h(x)+poly_m(x)
var temp_m map[int]int //存储F(x)*poly_cipher(x)
var expon_cipher map[int]int //存储对应x位的次方
var decrypt_m map[int]int //存储解密的密文,poly_f_P(x)*temp_m(x)
func encrypt() { /*加密函数*/
var i int
var j int
var k int = 0
for i = 0; i < 7; i++ { /*计算P*r(x),并将结果存储到temp_r*/
temp_r[i] = P * poly_r[i]
//fmt.Println(poly_h[i])
}
poly_cipher = make(map[int]int)
expon_cipher = make(map[int]int)
for i = 0; i < 7; i++ { /*两层for循环,计算temp_r(x)*poly_h(x)+poly_m(x)*/
for j = 0; j < 7; j++ {
poly_cipher[k] = temp_r[i] * poly_h[j]
//fmt.Print(poly_cipher[1])
if k > 6 { /*将指数相同的位数的系数相加*/
expon_cipher[k] = (i + j) % 7
switch expon_cipher[k] {
case 0:
poly_cipher[0] += poly_cipher[k]
//fmt.Println(poly_cipher[0])
case 1:
poly_cipher[1] += poly_cipher[k]
case 2:
poly_cipher[2] += poly_cipher[k]
case 3:
poly_cipher[3] += poly_cipher[k]
/*fmt.Print("当前次方=%d,对应数字为%d,k=", expon_cipher[k], poly_cipher[k], k, i, j, poly_cipher[1])
fmt.Println("\n")*/
case 4:
poly_cipher[4] += poly_cipher[k]
case 5:
poly_cipher[5] += poly_cipher[k]
case 6:
poly_cipher[6] += poly_cipher[k]
default:
fmt.Printf("未知型")
}
}
//fmt.Println(expon_cipher[k])
k++
}
//fmt.Println("\n")
poly_cipher[i] += poly_m[i] /*+m(x)操作*/
//fmt.Println("当前明文为:", poly_m[i])
//poly_cipher[i] = poly_cipher[i] % Q
//fmt.Println(poly_cipher[i])
}
//fmt.Println(poly_cipher[0])
for i = 0; i < 7; i++ { /*模Q操作,此时Q=29*/
poly_cipher[i] = poly_cipher[i] % Q
//fmt.Println(poly_cipher[i])
}
//fmt.Println(k)
}
func decrypt() { /*解密函数*/
var i int
var j int
var k int = 0
temp_m = make(map[int]int)
for i = 0; i < 7; i++ { /*双层for循环计算poly_f(x)*poly_cipher(x)*/
//fmt.Println(poly_cipher[1])
for j = 0; j < 7; j++ {
temp_m[k] = poly_f[i] * poly_cipher[j]
//fmt.Println("location=", k)
//fmt.Println("对应数字为=", temp_m[k])
if k > 6 { /*将指数相同的位数的系数相加*/
expon_cipher[k] = (i + j) % 7
switch expon_cipher[k] {
case 0:
temp_m[0] += temp_m[k]
case 1:
//fmt.Println(temp_m[1])
temp_m[1] += temp_m[k]
//fmt.Print("当前次方=%d,对应数字为%d,k=", expon_cipher[k], i, j, temp_m[k], temp_m[1])
//fmt.Println("\n")
case 2:
temp_m[2] += temp_m[k]
case 3:
temp_m[3] += temp_m[k]
/*fmt.Print("当前次方=%d,对应数字为%d,k=", expon_cipher[k], temp_m[k], k, i, j, temp_m[1])
fmt.Println("\n")*/
case 4:
temp_m[4] += temp_m[k]
case 5:
temp_m[5] += temp_m[k]
case 6:
temp_m[6] += temp_m[k]
default:
fmt.Printf("未知型")
}
}
k++
}
}
//fmt.Println(k)
for i = 0; i < 7; i++ { /*模Q操作,此时Q=29
由于此时的结果均在[-Q/2,Q/2]之间,所以没有进行center lift操作。*/
temp_m[i] = temp_m[i] % Q
//fmt.Println(temp_m[i])
}
var half_Q int = Q / 2
for i = 0; i < 7; i++ { /*center lift操作,不在[-Q/2,Q/2]之间的,正数-Q,负数+Q。前提对Q已经取模*/
if temp_m[i] > half_Q && temp_m[i] > 0 {
temp_m[i] = temp_m[i] - Q
fmt.Println(temp_m[i])
} else if temp_m[i] < -half_Q && temp_m[i] < 0 {
temp_m[i] = temp_m[i] + Q
}
}
decrypt_m = make(map[int]int)
k = 0
for i = 0; i < 7; i++ { /*双层for循环计算poly_f_P(x)*temp_m(x)*/
//fmt.Println(poly_cipher[1])
for j = 0; j < 7; j++ {
decrypt_m[k] = poly_f_P[i] * temp_m[j]
//fmt.Println("location=", k)
//fmt.Println("对应数字为=", decrypt_m[k])
if k > 6 { /*将指数相同的位数的系数相加*/
expon_cipher[k] = (i + j) % 7
switch expon_cipher[k] {
case 0:
decrypt_m[0] += decrypt_m[k]
case 1:
//fmt.Println(decrypt_m[1])
decrypt_m[1] += decrypt_m[k]
//fmt.Print("当前次方=%d,对应数字为%d,k=", expon_cipher[k], i, j, decrypt_m[k], decrypt_m[1])
//fmt.Println("\n")
case 2:
decrypt_m[2] += decrypt_m[k]
case 3:
decrypt_m[3] += decrypt_m[k]
/*fmt.Print("当前次方=%d,对应数字为%d,k=", expon_cipher[k], decrypt_m[k], k, i, j, decrypt_m[1])
fmt.Println("\n")*/
case 4:
decrypt_m[4] += decrypt_m[k]
case 5:
decrypt_m[5] += decrypt_m[k]
case 6:
decrypt_m[6] += decrypt_m[k]
default:
fmt.Printf("未知型")
}
}
k++
}
}
//fmt.Println(k)
for i = 0; i < 7; i++ { /*模P操作,此时P=2*/
decrypt_m[i] = decrypt_m[i] % P
fmt.Println(decrypt_m[i])
}
}
func main() {
encrypt()
decrypt()
}
手动验证计算过程:
手动验证计算过程确实有误,后面给我弟讲的时候发现的。当时博文也写好,后面就一直没有改!大家先把上面英文例子看懂了,可以自己手动验证计算过程的。