模乘的算法
❶ 两个向量的模相乘
向量a*向量b=|向量a|×|向量b|×cosa。(a为向量a和向量袜茄b的夹角),腔备所以|a|×|b|=(向量a*向量b)÷cosa=(x1x2+y1y2)÷cosa。若有疑问请追问伍好毁,希望对你有所帮助!
❷ 向量a的模乘以b的模等于什么
向量的液橘粗模等于各个闹镇分量的平方和的二次根,所以,a的模是2,b的模是3,他们的乘积等于6.
如果你是伍简要算向量的数量积(内积)的话,应该是对应分量乘积再求和,也就是说向量a和b的内积等于2*1+0*(-2)+0*(-2)=2.
❸ 关于模乘的算法
RSA算法中用到的大数运算
C. 大数的运算
1. 大数的运算原理
RSA算法依赖于大数的运算,目前主流RSA算法都建立在512位到1024位的大数运算之
上,所以我们首先需要掌握大数(比如1024位)的运算原理。
大多数的编译器只能支持到32位(或64位)的整数运算,即我们在运算中所使用的
整数必须小于等于32位,即0xFFFFFFFF,这远远达不到RSA的需要,于是需要专门建
立大数运算库,来解决这一问题。
最简单的办法是将大数当作字符串进行处理,也就是将大数用10进制字符数组进行
表示,然后模拟人们手工进行“竖式计算”的过程编写其加减乘除函数。但是这样
做效率很低。当然其优点是算法符合人们的日常习惯,易于理解。
另一种思路是将大数当作一个二进制流进行处理,使用各种移位和逻辑操作来进行
加减乘除运算,但是这样做代码设计非常复杂,可读性很低,难以理解也难以调试
。
这里我们采用了一种介于两者之间虚腊的思路:将大数看作一个N进制数组,对于目前的
32位系统而言,N可以取2的32次方,即0x100000000,假如将一个1024位的大数转化
成0x10000000进制,它就变成了32位,而每一位的取值范围是0-0xFFFFFFFF。我们
正好可以用一个无符号长整数来表罩侍示这一数值。所以1024位的大数就是一个有32个
元素的unsigned long数组。而且0x100000000进制的数组排列与2进制流对于计算机
来说,实际上是一回事,但是我们完全可以针对unsigned long数组进行“竖式计算
”,而循环规模被降低到物誉吵了32次之内,并且算法很容易理解。
但考虑到乘法和除法,都要进行扩展才能进行快速的计算(如果把除法变减法而不
扩展,速度将慢的无法忍受)。所以我们将N取2的16次方的,即0xFFFF。每一位用
unsigned short来表示,当进行乘除运算时,将short扩展成long,这是编译器所支
持的,所以运算起来,比较快。
❹ 如何进行幂模运算
模幂乘运算采用平方乘算法,将模幂乘运算转化为模乘和模平方运算实现.
平方-乘算法:一般地,求S=ABmodN,其中A<N,B<N;将指数B表示为二进制,即
观察算法,由于指数B化为二进制后的长度不确定,多数情况下高位会存在很多个0.如果完全按照该算法实现,指数B从最高位起开始运算,在第一个1出现以前,虽进行了多次运算,但D的值一直为1;当B出现第一个1后才进入有效的模乘运算.在具体实现时,设计专门的电路从高到低扫描指数B的每一位,当在找到第一个1之前,不做任何运算,找到第一个1时,使D=A,以后根据每次扫描的6[i]值,调用模乘实现运算.
经过对多种公钥加解密算法的分析——如RSA算法,通常公钥的有效位较短,而私钥有效位较长.加密中的模幂乘运算,指数有效位很少,所以上面的改进可大大减少模乘次数,加快加密过程.以目前常用的私钥和模数1 024 bit,公钥128bit情况为例,采用上述改进可减少896次不必要的模乘.解密过程使用中国余数定理(CRT),可有效降低解密指数的长度,整个算法的执行效率得到进一步提高.
2.2 模乘及模加的实现方法
模乘采用改进的Blakley加法型算法,原理与平方-乘算法类似,核心是将模乘转化为模加实现.如通常S=(A×B)modN,A<N,B<N可以按如下方式考虑.
将B表示成二进制:
由上式可知,可以像平方一乘算法一样,将模乘转化为模加实现.
一般模加运算表示为S=(A+B)modN,观察以上模乘及模幂乘算法原理描述,可知在其调用的模加运算中,因为A<N且B<N,则(A+B)<2N,所以,
因此考虑在运算中同时计算(A+B)和(A+B-N)两个结果,运算完成后通过判断加法器与减法器的进位输出(CO)与借位输出(BO).决定哪个为本次模加的正确结果.同上,A,B,N均为l位的二进制数,若CO=1,则说明(A+B)为l+1位二进制数,必大于l位的N;若CO=0,则(A+B)和N同为l位,当BO=1时(A+B)<N,当BO=0时N≤(A+B).
从而可以在一次运算中完成加法和求模过程,使模加的运算速度提高1倍.
❺ 向量模长的乘积公式
向量的模相乘公式是a·b=|a||b|cosθ。
向量AB的长度叫做枝绝扮向量的模,记作|AB|或|a|。向宏则量的模的运算没有专门的法则,一般都是通过余弦定理计算两个向量的和、差的模。
多个向量的合成用正交分解法,如果要求模一般需要先算出合成后的向量。模是绝对值在二维和三维空间的推广,可以认为就是向量的长度。推广到高维空间中称为范数。
公式方法:
两个向量的数量积(内积、点积)是一个数量(没有方向),记作a·b。向量的数量猛灶积的坐标表示:a·b=x·x'+y·y'。
两个向量a和b的向量积(外积、叉积)是一个向量,记作a×b这里“×”并不是乘号,只是一种表示方法,与“·”不同,也可记做“∧”。
若a、b不共线,则a×b的模是:∣a×b∣=|a|·|b|·sin〈a,b〉;a×b的方向是:垂直于a和b,且a、b和a×b按这个次序构成右手系。若a、b垂直,则∣a×b∣=|a|*|b。
❻ 用C或者C++语言实现这些多精度模乘算法。包括:32bit*32bit,64bit*64bit,128bit*128bit,256bit*256bit
把我的高精度模版 贴一下, 完全可以实现 256bit
。。。。。。。。。。。歼早。。。。氏盯雀。。。。。。。。。。。。。。
#include<iostream>
#include<string>
#include<iomanip>
#include<algorithm>
using namespace std;
class BigNum;
istream& operator>>(istream&, BigNum&);
ostream& operator<<(ostream&, BigNum&);
#define MAXN 9999
#define MAXSIZE 20000 //这是大数的位数,一个数组元素存储四位,那么一共就是20000*4 位数。
#define DLEN 4
class BigNum
{
public:
int a[MAXSIZE]; //数组模拟大数,一个数组元素存储四位数。
int len;
public:
BigNum(){len = 1;memset(a,0,sizeof(a));}
BigNum(const int);
BigNum(const char*);
BigNum(const BigNum &);
BigNum &operator=(const BigNum &);
friend istream& operator>>(istream&, BigNum&);
friend ostream& operator<<(ostream&, BigNum&);
BigNum operator*(const BigNum &) const;
};
//输入重载
istream& operator>>(istream & in, BigNum & b)
{
char ch[MAXSIZE*4];
int i = -1;
memset(b.a,0,sizeof(b.a));
in>>ch;
int l=strlen(ch);
int count=0,sum=0;
for(i=l-1;i>=0;)
{
sum = 0;
int t=1;
for(int j=0;j<4&&i>=0;j++,i--,t*=10)
{
sum+=(ch[i]-'0')*t;
}
b.a[count]=sum;
count++;
}
b.len =count++;
return in;
}
//输出重载则粗。
ostream& operator<<(ostream& out, BigNum& b)
{
int i;
cout << b.a[b.len - 1];
for(i = b.len - 2 ; i >= 0 ; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << b.a[i];
}
return out;
}
//下面是构造函数。
BigNum::BigNum(const int b)
{
int c,d = b;
len = 0;
memset(a,0,sizeof(a));
while(d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1); a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char*s)
{
int t,k,index,l;
memset(a,0,sizeof(a));
l=strlen(s);
len=l/DLEN;
if(l%DLEN)len++;
index=0;
for(int i=l-1;i>=0;i-=DLEN)
{
t=0;k=i-DLEN+1;
if(k<0)k=0;
for(int j=k;j<=i;j++)
t=t*10+s[j]-'0';
a[index++]=t;
}
}
BigNum::BigNum(const BigNum & T) : len(T.len)
{
int i;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++) a[i] = T.a[i];
}
////////////////////////////////////////////////
//赋值重载。
BigNum & BigNum::operator=(const BigNum & n)
{
len = n.len;
memset(a,0,sizeof(a));
for(int i = 0 ; i < len ; i++)
a[i] = n.a[i];
return *this;
}
//乘法重载。
BigNum BigNum::operator*(const BigNum & T) const
{
BigNum ret;
int i,j,up;
int temp,temp1;
for(i = 0 ; i < len ; i++)
{
up = 0;
for(j = 0 ; j < T.len ; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if(temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if(up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while(ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--;
return ret;
}
/*****************************************/
int main()
{
BigNum a,b,c;
cin>>a>>b; //输入大数。
c=a*b; //计算a*b
cout<<c<<endl; //输出c
return 0;
}
❼ 向量被拆成几个向量后模相乘怎么算
算法如下:
向量a=(x1,y1),向量b=(x2,y2);a·b=x1x2+y1y2=|a||b|cosθ(θ是a,b夹角);
向量之间不叫乘积,而叫数量积。如a·b叫做a与b的数量积或a点乘b;
向量积,数学中又称外积、叉积,物理中称矢积、叉乘,是历备一种在向量空间中向量的二元运算。慧唤
与点积不同,它肢碧毁的运算结果是一个向量而不是一个标量。
❽ RSA里的mod计算问题
RSA软件算法以及硬件实现都是利用蒙哥马利模乘实现你的要求的
由于RSA
的核心算法是模幂运算,模幂运算又相当于模乘运算的循环,要提高
RSA
算法的效率,首要问题在于提高模乘运算的效率。不难发现,模乘过程中复杂
度最高的环节是求模运算,因为一次除法实际上包含了多次加法、减法和乘法,如
果在算法中能够尽量减少除法甚至避免除法,则算法的效率会大大提高。
设A=Sum[i=0
to
k](A*2**i),0<=A<=1,则:
C=
A*B
=
Sum[i=0
to
k](A*B*2**i)
可用循环处理为:
C=0
FOR
i
FROM
k
TO
0
C=C*2
C=C+A*B
RETURN
C
若令
C'=
A*B*2**(-k),则:
C'=
Sum[i=0
to
k](A*B*2**(i-k))
用循环处理即:
C'=0
FOR
i
FROM
0
TO
k
C'=C'+A*B
C'=C'/2
RETURN
C'
通过这一算法求A*B*2**(-k)是不精确的,因为在循环中每次除以2都可能有余
数被舍弃了,但是可以通过这一算法求A*B*2**(-k)
%N的精确值,方法是在对C'除
2之前,让C'加上C'[0]*N。由于在RSA中N是两个素数的积,总是奇数,所以当C'是
奇数时,C'[0]=1,C'+C'[0]*N
就是偶数,而当C'为偶数时C'[0]=0,C'+C'[0]*N
还是偶数,这样C'/2
就不会有余数被舍弃。又因为C'+N
%N
=
C'
%N,所以在计算
过程中加若干次N,并不会影响结果的正确性。可以将算法整理如下:
C'=0
FOR
i
FROM
0
TO
k
C'=C'+A*B
C'=C'+C'[0]*N
C'=C'/2
IF
C'>=N
C'=C'-N
RETURN
C'
由于在RSA中A、B总是小于N,又0<=A,C'[0]<=1,所以:
C'
=
(C'+A*B+C'[0]*N)/2
C'
<
(C'+2N)/2
2C'
<
C'+2N
C'
<
2N
既然C'总是小于2N,所以求C'
%N
就可以很简单地在结束循环后用一次减法来
完成,即在求A*B*2**(-k)
%N的过程中不用反复求模,达到了我们避免做除法的目
的。当然,这一算法求得的是A*B*2**(-k)
%N,而不是我们最初需要的A*B
%N。但
是利用A*B*2**(-k)我们同样可以求得A**E
%N。
设R=2**k
%N,R'=2**(-k)
%N,E=Sum[i=0
to
n](E*2**i):
A'=A*R
%N
X=A'
FOR
i
FROM
n
TO
0
X=X*X*R'
%N
IF
E=1
X=X*A'*R'
%N
X=X*1*R'
%N
RETURN
X
最初:
X
=
A*R
%N,
开始循环时:
X
=
X*X*R'
%N
=
A*R*A*R*R'
%N
=
A**2*R
%N
反复循环之后:
X
=
A**E*R
%N
最后:
X
=
X*1*R'
%N
=
A**E*R*R'
%N
=
A**E
%N
如此,我们最终实现了不含除法的模幂算法,这就是着名的蒙哥马利算法,而
X*Y*R'
%N
则被称为“蒙哥马利模乘”。以上讨论的是蒙哥马利模乘最简单,最容
易理解的二进制形式。蒙哥马利算法的核心思想在于将求A*B
%N转化为不需要反复
取模的A*B*R'
%N,但是利用二进制算法求1024位的A*B*R'
%N,需要循环1024次之
多,我么必然希望找到更有效的计算A*B*R'
%N的算法。
考虑将A表示为任意的r进制:
A
=
Sum[i=0
to
k](A*r**i)
0<=A<=r
我们需要得到的蒙哥马利乘积为:
C'=
A*B*R'
%N
R'=r**(-k)
则以下算法只能得到C'的近似值
C'=0
FOR
i
FROM
0
TO
k
C'=C'+A*B
C'=C'/r
IF
C'>=N
C'=C'-N
RETURN
C'
因为在循环中每次C'=C'/r
时,都可能有余数被舍弃。假如我们能够找到一个
系数
q,使得(C'
+
A*B
+
q*N)
%r
=0,并将算法修改为:
C'=0
FOR
i
FROM
0
TO
k
C'=C'+A*B+q*N
C'=C'/r
IF
C'>=N
C'=C'-N
RETURN
C'
则C'的最终返回值就是A*B*R'
%N的精确值,所以关键在于求q。由于:
(C'
+
A*B
+
q*N)
%r
=0
==>
(C'
%r
+
A*B
%r
+
q*N
%r)
%r
=0
==>
(C'[0]
+
A*B[0]
+
q*N[0])
%r
=0
若令N[0]*N[0]'
%r
=1,q=(C'[0]+A*B[0])*(r-N[0]')
%r,则:
(C'[0]
+
A*B[0]
+
q*N[0])
%r
=
(C'[0]+A*B[0]
-
(C'[0]+A*B[0])*N[0]'*N[0])
%r)
%r
=
0
于是我们可以得出r为任何值的蒙哥马利算法:
m=r-N[0]'
C'=0
FOR
i
FROM
0
TO
k
q=(C'[0]+A*B[0])*m
%r
C'=(C'+A*B+q*N)/r
IF
C'>=N
C'=C'-N
RETURN
C'
如果令
r=0x100000000,则
%r
和
/r
运算都会变得非常容易,在1024位的运
算中,循环次数k
不大于32,整个运算过程中最大的中间变量C'=(C'+A*B+q*N)
<
2*r*N
<
1057位,算法效率就相当高了。唯一的额外负担是需要计算
N[0]',使
N[0]*N[0]'
%r
=1,而这一问题前面已经用欧几里德算法解决过了,而且在模幂运
算转化成反复模乘运算时,N是固定值,所以N[0]'只需要计算一次,负担并不大。
❾ 密码学中模加 模乘是如何运算的
都高清是求余.
模核乎加是加后求余,改念悉模乘是乘后求余。
3*8 mod 5=24mod 5=4,3+8 mod 5=11mod 5=1
❿ 两个模相乘怎么算
先算 |3a+4b|^2=9a^2+24ab+16b^2 从而算出|3a+4b| 的贺改游值,同理再算出|2a+b|的值禅销,再两歼清者相乘即可