NTRU-密码学

在介绍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希望发送明文消息
Bob的临时密钥为r。
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()
}

手动验证计算过程:
手动验证计算过程确实有误,后面给我弟讲的时候发现的。当时博文也写好,后面就一直没有改!大家先把上面英文例子看懂了,可以自己手动验证计算过程的。
在这里插入图片描述


评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值