密码学的数学基础1

本文为密码学的数学基础(王小云,王明强著)的读书笔记,将自己认为比较好的定理的证明与习题做了整理,同时对一些常用的算法做了拓展,以及C语言的实现,水平有限,如有错误,欢迎指正。(PS:官方编辑器好多公式不方便编辑,于是便从latex中粘过来图片,使局部地区不太美观,多多包涵)

素数,整除

两个定理

定理1.4:若a为合数,则a的最小真因子为素数。
定理1.5:素数又无穷多个。

证明:

1.4:
反证法,假设a为合数,即 a > 2 a>2 a>2,设其最小真因子为d,那么假设d为非素数,即为合数,存在 d ′ ∣ d d'|d dd,因此 d ′ ∣ a d'|a da,所以,与d为最小真因子矛盾,得证.
1.5:
反证法,假设素数为有限个,为 p 1 , p 2 , p 3 , . . . p k p_1,p_2,p_3,...p_k p1,p2,p3,...pk,考虑 a = p 1 p 2 . . . p k + 1 , a=p_1p_2...p_k+1, a=p1p2...pk+1,那么根据定理1.4,可以得到a的最小真因子一定为 p 1 , p 2 , p 3 , . . . p k p_1,p_2,p_3,...p_k p1,p2,p3,...pk中某一个素数,记作p,则 p 为 p i ( i = 1 , 2 , . . . k ) 中 某 一 个 , p为p_{i}(i=1,2,...k)中某一个, ppi(i=1,2,...k),所以 p ∣ a , p ∣ p 1 p 2 . . . p k p|a,p|p_{1}p_{2}...p_k pa,pp1p2...pk同时成立,所以推出p|1,这与p为素数矛盾,得证.

最大公因子,最小公倍数

数学符号定义
求a和b的最大公因子: d = g c d ( a , b ) = ( a , b ) d=gcd(a,b)=(a,b) d=gcd(a,b)=(a,b)
求a和b的最小公倍数: [ a , b ] [a,b] [a,b]

一道证明题

题目:
设a是奇数,证明:

  1. 一定存在正整数 d ≤ a − 1 , 使 得 a ∣ 2 d − 1 d\leq a-1,使得a|2^{d}-1 da1,使a2d1
  2. 必有正整数d,使 ( 2 d − 3 , a ) = 1 (2^d-3,a)=1 (2d3,a)=1

证明:

考虑以下a个数 2 0 , 2 1 , 2 2 , . . . 2 a − 1 2^0,2^1,2^2,...2^{a-1} 20,21,22,...2a1 a ∤ 2 j ( 0 ≤ j < a ) a\nmid2^j(0\leq j<a ) a2j(0j<a)以及带余除法可以得到知道,对于每一个j, 0 ≤ j < a 0 \leq j<a 0j<a,存在 q j , r j q_j,r_j qj,rj使得 2 j = q j a + r j , 0 < r j < a 2^j=q_ja+r_j,0<r_j<a 2j=qja+rj,0<rj<a所以a个余数 r 0 , r 1 , . . . r a − 1 r_0,r_1,...r_{a-1} r0,r1,...ra1 仅仅可能取a-1个值,根据抽屉原理知道其中必有两个余数相等,不妨设 0 ≤ i < k < a 0\leq i<k<a 0i<k<a,且 r i = r k r_i=r_k ri=rk,因而有 a ( q k − q i ) = 2 k − 2 i = 2 i ( 2 k − i − 1 ) a(q_k-q_i)=2^k-2^i=2^i(2^{k-i}-1) a(qkqi)=2k2i=2i(2ki1) ( a , 2 ) = 1 (a,2)=1 (a,2)=1,可以得到 a ∣ 2 k − i − 1 a|2^{k-i}-1 a2ki1 d = k − i d=k-i d=ki即满足要求.得证
2.
由1知,存在d使得 a ∣ 2 d − 1 a|2^{d}-1 a2d1,可以推出 ( 2 d − 3 , a ) = ( 2 d − 1 − 2 , a ) = ( − 2 , a ) = 1 (2^d-3,a)=(2^d-1-2,a)=(-2,a)=1 (2d3,a)=(2d12,a)=(2,a)=1得证.

Euclid

算法定义与应用

定义:
euclid算法定义
Euclid算法重要结论:
(1) r k = ( a , b ) r_{k}=(a, b) rk=(a,b)
(2) 存在整数 x 0 , x 1 x_{0}, x_{1} x0,x1 使 ( a , b ) = a x 0 + b x 1 (a, b)=a x_{0}+b x_{1} (a,b)=ax0+bx1\
证明:
(1) 从Euclid算法定义的最后一个式子,依次往上推,可得
r k = ( r k , r k − 1 ) = ⋯ = ( r 1 , r 0 ) = ( r 0 , b ) = ( a , b ) r_{k}=\left(r_{k}, r_{k-1}\right)=\cdots=\left(r_{1}, r_{0}\right)=\left(r_{0}, b\right)=(a, b) rk=(rk,rk1)==(r1,r0)=(r0,b)=(a,b)
结论成立.
(2) 由 Euclid 算法中的第 k + 1 k+1 k+1 式, ( a , b ) (a, b) (a,b) 可表成 r k − 1 r_{k-1} rk1 r k − 2 r_{k-2} rk2 的整系数线性组合, 利用第 k + 1 k+1 k+1 式可消去 r k − 1 , r_{k-1}, rk1, 得到 ( a , b ) (a, b) (a,b) 的关于 r k − 2 r_{k-2} rk2 r k − 3 r_{k-3} rk3 的整系数线性组合. 这样依次利用第 k , k − 1 , ⋯   , 2 , 1 k, k-1, \cdots, 2,1 k,k1,,2,1 式, 就得到 a a a b b b 的整系数线性组合.

Euclid应用之一:求最大公因子

//输入参数设定:a>b(进入函数前需要判断,使a>b),可以加快求解速度,
//避免了递归函数中的判断
int Euclid(int a,int b)
 {
	if(!b)
 		return a;//如果b=0,a为最大公因子,返回a
	return Euclid(b,a%b);
 }

拓展Euclid算法介绍与实现

拓展Euclid算法在求解不定方程和密码学中有着极其重要的作用,比如:

  • 在求解不定方程中,常常用Euclid求解.
  • 当两个数互素,即最大公因子为1时,在RSA加密算法中,常常利用拓展Eclid,根据公钥求私钥.
  • 待补充…

通过拓展Euclid算法求解两个数a和b的线性组合式,是拓展Eclid算法的重要应用,即求解满足 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的x,y值,可以作为不定方程的某一个特解.如果 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1再利用同余性质,进行求a或b的逆.
下面为求解满足 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的x,y值的代码与解析.
对x,y值求解有两种方法,一种递归式方案,一种非递归式方案,递归方案代码简单,阅读代码比较困难,资源开销较大.非递归方案代码较复杂,但是逻辑简单,易读,资源开销较小.下面,对其分别进行解析:

非递归方案:

非递归Eclid算法
在这里插入图片描述
图片来源
C语言代码:

//输入参数设定:a>b(进入函数前需要判断,使a>b),gcd为a和b的最大公因子,x,y为相应解
 void ex_Euclid_Non_recursive(int a, int b, int& gcd, int& x, int& y)
{
	int r_1 = a, r0 = b, x_1 = 1, y_1 = 0,
	 x0 = 0, y0 = 1,x1=1,y1=0, q1,tempX,tempY,Temp;//初始化,r_{-1}定义为r_1,其余类推
	if (r0)
	{
		q1 = r_1 / r0;//初始化
		x1 = 1, y1 = -q1;
		while (r_1 % r0)
		{
			q1 = r_1 / r0;//初始化
			tempX = x1, tempY = y1;//将x1,y1存储到临时变量中
			x1 = x_1 - q1 * x0;
			y1 = y_1 - q1 * y0;
			//cout << x1 << '\t' << y1 << endl;
			x_1 = x0, y_1 = y0;
			x0 = tempX, y0 = tempY;
			Temp = r_1;//将r_1存储到临时变量中
			r_1 = r0;
			r0 = Temp % r0;
			//cout << r_1 << '\t' << r0 << endl;
		}
	}
	gcd = r0;
	x = x1, y = y1;
}

递归方案:

求解满足 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的x,y值.我们可以换一种思维:
和非递归方案类似,我们试图寻找 x 1 和 x 2 x_1和x_2 x1x2, y 1 和 y 2 y_1和y_2 y1y2之间的关系,不过不同的是,在非递归方案中,我们找到的是由已知的 x − 1 , y − 1 , x 0 , y 0 x_{-1},y_{-1},x_0,y_0 x1,y1,x0,y0求解 x 1 , y 1 x_1,y_1 x1,y1的方案,即按照计算的过程,循序渐进寻找答案,这次我们寻找一种反向的求解方法,即由 x 2 , y 2 x_2,y_2 x2,y2求解 x 1 , y 1 x_1,y_1 x1,y1,这就需要我们进行利用递归函数特性,进行求解:
通过欧几里得算法定义观察以下两个等式**(注意:以下的%为C语言种的含义,即取余,/为C语言含义,即除法取整)** a x 1 + b y 1 = g c d ( a , b ) ax_1+by_1=gcd(a,b) ax1+by1=gcd(a,b) b x 2 + ( a % b ) y 2 = g c d ( b , a % b ) bx_2+(a\%b)y_2=gcd(b,a\%b) bx2+(a%b)y2=gcd(b,a%b)由于 a x 1 + b y 1 = b x 2 + ( a % b ) y 2 = g c d ( a , b ) = g c d ( b , a % b ) ax_1+by_1=bx_2+(a\%b)y_2=gcd(a,b)=gcd(b,a\%b) ax1+by1=bx2+(a%b)y2=gcd(a,b)=gcd(b,a%b) a % b = a − ( a / b ) ∗ b a\%b=a-(a/b)*b a%b=a(a/b)b
整理以上四个等式可以得到: a x 1 + b y 1 = b x 2 + ( a − ( a / b ) ∗ b ) y 2 ax_1+by_1=bx_2+(a-(a/b)*b)y_2 ax1+by1=bx2+(a(a/b)b)y2待定系数法化简后得到:
x 1 = y 2 x_1=y_2 x1=y2 y 1 = x 2 − ( a / b ) y 2 y_1=x_2-(a/b)y_2 y1=x2(a/b)y2以上两式即为我们得到的递归等式,函数出口为: a % b = 0 a\%b=0 a%b=0,此时x=1,y=0.
附上代码:

void ex_Euclid_recursive(int a, int b, int& gcd, int& x, int& y)
{
	if (b == 0)//递归函数出口
	{
		x = 1;
		y = 0;
		gcd = a;
	}
	else
	{
		ex_Euclid_recursive(b, a % b, gcd, y, x);
		//此时x为y_2,y为x_2,理解这句话是理解此递归函数的关键
		y -= x * (a / b);
	}

}

可能代码阅读难度比较大,我也是理解了好几个小时才啃下这一部分,但是,当想明白后,还是蛮有成就感的,加油!!

递归与非递归方案函数代码+测试代码:

#include<iostream>
using namespace std;
inline void swap(int& a, int& b) { a ^= b ^= a ^= b; }
void ex_Eclid_Non_recursive(int a, int b, int& gcd, int& x, int& y)
{
	int r_1 = a, r0 = b, x_1 = 1, y_1 = 0, x0 = 0, y0 = 1,x1=1,y1=0, q1,tempX,tempY,Temp;//初始化
	if (r0)
	{
		q1 = r_1 / r0;//初始化
		x1 = 1, y1 = -q1;
		while (r_1 % r0)
		{
			q1 = r_1 / r0;//初始化
			tempX = x1, tempY = y1;//将x1,y1存储到临时变量中
			x1 = x_1 - q1 * x0;
			y1 = y_1 - q1 * y0;
			//cout << x1 << '\t' << y1 << endl;
			x_1 = x0, y_1 = y0;
			x0 = tempX, y0 = tempY;
			Temp = r_1;//将r_1存储到临时变量中
			r_1 = r0;
			r0 = Temp % r0;
			//cout << r_1 << '\t' << r0 << endl;
		}
	}
	gcd = r0;
	x = x1, y = y1;
}
void ex_Eclid_recursive(int a, int b, int& gcd, int& x, int& y)
{
	if (b == 0)
	{
		x = 1;
		y = 0;
		gcd = a;
	}
	else
	{
		ex_Eclid_recursive(b, a % b, gcd, y, x);
		y -= x * (a / b);
	}

}

int main()
{
	int a = 11, b = 1732, gcd, x, y;
	if (a < b)swap(a, b), swap(x, y);
	ex_Eclid_Non_recursive(a, b,gcd, x, y);
	cout << "非递归方案:\n"<<"gcd=" << gcd << '\t' << "x=" << x << '\t' << "y=" << y << endl;
	cout << gcd << " = " << a << "X" << x << "+" << b << "X" << y << endl;
	gcd=0, x=0, y=0;//初始化为0,继续测试
	ex_Eclid_recursive(a, b, gcd, x, y);
	cout << "递归方案:\n" << "gcd=" << gcd << '\t' << "x=" << x << '\t' << "y=" << y << endl;
	cout << gcd << " = " << a << "X" << x << "+" << b << "X" << y << endl;
	return 0;
}

几个习题

  1. 对任意正整数 a 有 5 ∣ a 5 − a 5 \mid a^{5}-a 5a5a

  2. 13 ∣ a 2 − 7 b 2 13 \mid a^{2}-7 b^{2} 13a27b2 的充要条件是 13 ∣ a , 13 ∣ b 13|a, 13| b 13a,13b

  3. n > 1 n>1 n>1 时, 1 + 1 / 2 + ⋯ + 1 / n 1+1 / 2+\cdots+1 / n 1+1/2++1/n 不是整数

习题参考答案

  1. 充分性: 13 ∣ a 2 − 7 b 2 13 \mid a^{2}-7 b^{2} 13a27b2 时,我们要推出 13 ∣ a , 13 ∣ b 13|a, 13| b 13a,13b:
    13 ∣ a 2 − 7 b 2 13 \mid a^{2}-7 b^{2} 13a27b2等价于 a 2 = 7 b 2 ( m o d   13 ) a^{2}=7 b^{2}(mod\ 13) a2=7b2(mod 13),可以通过遍历a,b,a和b的取值范围均为0~12,进a=b=0时满足等式.所以充分性得证.(应该有更好的方法,暂时忘了,想到再补充…)
    必要性: 13 ∣ a , 13 ∣ b 13|a, 13| b 13a,13b时,我们要推出 13 ∣ a 2 − 7 b 2 13 \mid a^{2}-7 b^{2} 13a27b2:
    a = 13 r , b = 13 s , a=13r,b=13s, a=13r,b=13s,带入 13 ∣ a 2 − 7 b 2 13 \mid a^{2}-7 b^{2} 13a27b2,满足,得证.
  2. 假设存在这样一个n, 设k是不大于n的素数 ,由于素数和它的两倍 之间一定存在一个素数 ,所以n不大于2k ,即所有的分母中只有k含有因子k
    ,因为级数是整数 。
    所以除开 1 / k 1/k 1/k的其他数的和的小数部分是 ( k − 1 ) / k (k-1)/k (k1)/k ,因为其它分母中均不含有素数k这个因子 ,所以这些分数的和也不含有素数k
    两者矛盾
    所以不存在这样一个n

参考博客1
参考博客2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值