//rsa.h
#include<stdio.h>
#defineMAX_NUM63001
#defineMAX_PRIME251
//!返回代码
#defineOK100
#defineERROR_NOEACHPRIME101
#defineERROR_NOPUBLICKEY102
#defineERROR_GENERROR103
unsignedintMakePrivatedKeyd(unsignedintuiP,unsignedintuiQ);
unsignedintGetPrivateKeyd(unsignedintiWhich);
unsignedintMakePairkey(unsignedintuiP,unsignedintuiQ,unsignedintuiD);
unsignedintGetPairKey(unsignedint&d,unsignedint&e);
voidrsa_encrypt(intn,inte,char*mw,intiLength,int*&cw);
voidrsa_decrypt(intn,intd,int*&cw,intcLength,char*mw);
voidoutputkey();
//rsa.c
#include"rsa.h"
//!保存私钥d集合
structpKeyset
{
unsignedintset[MAX_NUM];
unsignedintsize;
}pset;
//!保存公、私钥对
structpPairkey
{
unsignedintd;
unsignedinte;
unsignedintn;
}pairkey;
//名称:isPrime
//功能:判断两个数是否互质
//参数:m:数a;n:数b
//返回:m、n互质返回true;否则返回false
boolisPrime(unsignedintm,unsignedintn)
{
unsignedinti=0;
boolFlag=true;
if(m<2||n<2)
returnfalse;
unsignedinttem=(m>n)?n:m;
for(i=2;i<=tem&&Flag;i++)
{
boolmFlag=true;
boolnFlag=true;
if(m%i==0)
mFlag=false;
if(n%i==0)
nFlag=false;
if(!mFlag&&!nFlag)
Flag=false;
}
if(Flag)
returntrue;
else
returnfalse;
}
//名称:MakePrivatedKeyd
//功能:由素数Q、Q生成私钥d
//参数:uiP:素数P;uiQ:素数Q
//返回:私钥d
unsignedintMakePrivatedKeyd(unsignedintuiP,unsignedintuiQ)
{
unsignedinti=0;
//!得到所有与z互质的数(私钥d的集合)
unsignedintz=(uiP-1)*(uiQ-1);
pset.size=0;
for(i=0;i<z;i++)
{
if(isPrime(i,z))
{
pset.set[pset.size++]=i;
}
}
returnpset.size;
}
//名称:MakePairKey
//功能:生成RSA公、私钥对
//参数:uiP:素数P;uiQ:素数Q;uiD:私钥d
//返回:错误代码
unsignedintMakePairkey(unsignedintuiP,unsignedintuiQ,unsignedintuiD)
{
boolbFlag=true;
unsignedinti=0,e;
unsignedintz=(uiP-1)*(uiQ-1);
unsignedintd=pset.set[uiD];
//d=uiD;
if(!isPrime(z,d))
returnERROR_NOEACHPRIME;
for(i=2;i<z;i++)
{
if((i*d)%z==1)
{
e=i;
bFlag=false;
}
}
if(bFlag)
returnERROR_NOPUBLICKEY;
if((d*e)%z!=1)
ERROR_GENERROR;
pairkey.d=d;
pairkey.e=e;
pairkey.n=uiP*uiQ;
returnOK;
}
//名称:GetPairKey
//功能:对外提供接口,获得公、私钥对
//参数:uiP:素数P;uiQ:素数Q;uiD:私钥d
//返回:
unsignedintGetPairKey(unsignedint&d,unsignedint&e)
{
d=pairkey.d;
e=pairkey.e;
returnpairkey.n;
}
//名称:GetPrivateKeyd
//功能:对外提供接口,由用户选择ID得以私钥d
//参数:iWhich:用户选择私钥d的ID
//返回:私钥d值
unsignedintGetPrivateKeyd(unsignedintiWhich)
{
if(pset.size>=iWhich)
returnpset.set[iWhich];
else
return0;
}
//名称:rsa_encrypt
//功能:RSA加密运算
//参数:n:公钥n;e:公钥e;mw:加密明文;iLength:明文长度;cw:密文输出
//返回:无
voidrsa_encrypt(intn,inte,char*mw,intmLength,int*&cw)
{
inti=0,j=0;
__int64temInt=0;
for(i=0;i<mLength;i++)
{
temInt=mw[i];
if(e!=0)
{
for(j=1;j<e;j++)
{
temInt=(temInt*mw[i])%n;
}
}
else
{
temInt=1;
}
cw[i]=(int)temInt;
}
}
//名称:rsa_decrypt
//功能:RSA解密运算
//参数:n:私钥n;d:私钥d;cw:密文;cLength:密文长度;mw:明文输出
//返回:无
voidrsa_decrypt(intn,intd,int*&cw,intcLength,char*mw)
{
inti=0,j=-1;
__int64temInt=0;
for(i=0;i<cLength/4;++i)
{
mw[i]=0;
temInt=cw[i];
if(d!=0)
{
for(j=1;j<d;j++)
{
temInt=(__int64)(temInt*cw[i])%n;
}
}
else
{
temInt=1;
}
mw[i]=(char)temInt;
}
}
voidoutputkey()
{
printf("PublicKey(e,n):(%d,%d) ",pairkey.e,pairkey.n);
printf("PrivateKey(d,n):(%d,%d) ",pairkey.d,pairkey.n);
}
//main.c
//工程:RSA
//功能:RSA加、解密文件
//作者:jlcss|ExpNIS
#include<stdio.h>
#include<afxwin.h>
#include<math.h>
#include"rsa.h"
#defineDECRYPT_FILE"RSA加密密文.txt"
#defineENCRYPT_FILE"RSA解密明文.txt"
//!约束文件最大2M
#defineMAX_FILE1024*1024*2
//名称:usage
//功能:帮助信息
//参数:应用程序名称
//返回:提示信息
voidUsage(constchar*appname)
{
printf(" usage:rsa-k素数P素数Q ");
printf(" usage:rsa-e明文文件公钥e公钥n ");
printf(" usage:rsa-d密文文件私钥d私钥n ");
}
//名称:IsNumber
//功能:判断数字字符数组
//参数:strNumber:字符数组
//返回:数字字组数组返回true,否则返回false;
boolIsNumber(constchar*strNumber)
{
unsignedinti;
if(!strNumber)
returnfalse;
for(i=0;i<strlen(strNumber);i++)
{
if(strNumber[i]<'0'||strNumber[i]>'9')
returnfalse;
}
returntrue;
}
//名称:IsPrimeNumber
//功能:判断素数
//参数:num:输入整数
//返回:素数返回true,否则返回false;
boolIsPrimeNumber(unsignedintnum)
{
unsignedinti;
if(num<=1)
returnfalse;
unsignedintsqr=(unsignedint)sqrt((double)num);
for(i=2;i<=sqr;i++)
{
if(num%i==0)
returnfalse;
}
returntrue;
}
//名称:FileIn
//功能:读取磁盘文件到内存
//参数:strFile:文件名称;inBuff:指向文件内容缓冲区
//返回:实际读取内容大小(字节)
intFileIn(constchar*strFile,unsignedchar*&inBuff)
{
intiFileLen=0,iBuffLen=0;
//!打开密文文件
CFilefile(strFile,CFile::modeRead);
iFileLen=(int)file.GetLength();
if(iFileLen>MAX_FILE)
{
printf("文件长度不能大于%dM,! ",MAX_FILE/(1024*1024));
gotoout;
}
iBuffLen=iFileLen;
inBuff=newunsignedchar[iBuffLen];
if(!inBuff)
gotoout;
ZeroMemory(inBuff,iBuffLen);
file.Read(inBuff,iFileLen);
file.Close();
out:
returniBuffLen;
}
//名称:FileOut
//功能:加/解密结果输出到当前目录磁盘文件中
//参数:strOut指向输出字符缓冲区,输出大小len,strFile为输出文件
//返回:无
voidFileOut(constvoid*strOut,intlen,constchar*strFile)
{
//!输出到文件
CFileoutfile(strFile,CFile::modeCreate|CFile::modeWrite);
outfile.Write(strOut,len);
outfile.Close();
}
//名称:CheckParse
//功能:校验应用程序入口参数
//参数:argc等于main主函数argc参数,argv指向main主函数argv参数
//返回:若参数合法返回true,否则返回false
//备注:简单的入口参数校验
boolCheckParse(intargc,char**argv)
{
boolbRes=false;
if(argc!=4&&argc!=5)
gotoout;
if(argc==4&&argv[1][1]=='k')
{
//!生成公、私钥对
if(!IsNumber(argv[2])||
!IsNumber(argv[3])||
atoi(argv[2])>MAX_PRIME||
atoi(argv[3])>MAX_PRIME)
gotoout;
}
elseif((argc==5)&&(argv[1][1]=='e'||argv[1][1]=='d'))
{
//!加密、解密操作
if(!IsNumber(argv[3])||
!IsNumber(argv[4])||
atoi(argv[3])>MAX_NUM||
atoi(argv[4])>MAX_NUM)
gotoout;
}
else
Usage(*argv);
bRes=true;
out:
returnbRes;
}
//名称:kOption1
//功能:程序k选项操作:由素数P、Q生成私钥d集合
//参数:uiP:程序入口参数P;uiQ:程序入口参数Q
//返回:执行正确返回生成私钥数目,否则返回0
unsignedintkOption1(unsignedintuiP,unsignedintuiQ)
{
unsignedintuiRes=0;
if(!IsPrimeNumber(uiP))
{
printf("P输入错误,P必须为(0,%d]素数",MAX_PRIME);
returnuiRes;
}
if(!IsPrimeNumber(uiQ))
{
printf("Q输入错误,Q必须为(0,%d]素数",MAX_PRIME);
returnuiRes;
}
if(uiP==uiQ)
{
printf("素数P与素数Q相同,很容易根据公钥n开平方得出素数P和Q,这种加密不安全,请更换素数! ");
returnuiRes;
}
printf("正在生成私钥d集合...... ");
uiRes=MakePrivatedKeyd(uiP,uiQ);
returnuiRes;
}
//!程序主函数
intmain(intargc,char**argv)
{
unsignedintp,q,d,n,e;//twoprimep&q,publickey(n,e),privatekey(n,d)
CheckParse(argc,argv);
d=4828;//uid
if(argc==4)
{
p=atoi(argv[2]);
q=atoi(argv[3]);
MakePrivatedKeyd(p,q);
MakePairkey(p,q,d);
outputkey();
}
elseif(argc==5)
{
charFileName[20];
strcpy(FileName,argv[2]);
intlen;
if(argv[1][1]=='e')
{
unsignedchar*inBuffer=(unsignedchar*)malloc(MAX_FILE);//输入缓冲区
int*cw=(int*)malloc(MAX_FILE);
len=FileIn(FileName,inBuffer);
e=atoi(argv[3]);
n=atoi(argv[4]);
rsa_encrypt(n,e,(char*)inBuffer,len,cw);
FileOut(cw,4*len,DECRYPT_FILE);
}
elseif(argv[1][1]=='d')
{
char*Buffer=(char*)malloc(MAX_FILE);//输入缓冲区
int*cw=(int*)malloc(MAX_FILE);
len=FileIn(FileName,(unsignedchar*&)cw);
d=atoi(argv[3]);
n=atoi(argv[4]);
rsa_decrypt(n,d,cw,len,Buffer);
FileOut(Buffer,len/4,ENCRYPT_FILE);
}
}
return0;
}
❷ 密码学问题 为什么RSA数字签名一定要先签名、后加密我是初学者,谢谢!!!
我是这么觉得:
签名的一个目的是:防止签名双方抵赖。
如果先加密的话,到时候他有可能不认账。
而且,特别是针对RSA签名算法,有一种专门针对先加密后签名的攻击。为了防止这种攻击,推荐采用先签名后加密。
这种攻击方法为:
假设签名者A用先加密后签名的方法把消息x发给B,他是先用B的公钥eb对x加密,然后用自己的私钥da签名,设A的模数为na,B的为nb,那么,A发给B的密文为: (x^eb mod nb)^da mod na
如果B不诚实,那么B可能伪造A的签名。谎称收到的是x1.因为nb是B的模数,所以B知道nb的分解,于是可以计算模nb的离散对数。 (x1)^k=x mod nb
之后,B再公布他的新公钥。然后宣布收到的是x1不是x。
❸ RSA为什么先签名后加密
签名是用私钥来计算的。所以签名不能随便签。对明文签名可以理解。对密文签名,你并不知道密文的内容,一旦对密文签名,就可能出现这样一种情况。有人想破译一段发给你的密文,他把这段密文伪装成需要你来签名的内容,你签名后就是明文了。
❹ rsa加密解密算法
1978年就出现了这种算法,它是第一个既能用于数据加密
也能用于数字签名的算法。它易于理解和操作,也很流行。算
法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和
Leonard Adleman。但RSA的安全性一直未能得到理论上的证明。
RSA的安全性依赖于大数分解。公钥和私钥都是两个大素数
( 大于 100个十进制位)的函数。据猜测,从一个密钥和密文
推断出明文的难度等同于分解两个大素数的积。
密钥对的产生:选择两个大素数,p 和q 。计算:
n = p * q
然后随机选择加密密钥e,要求 e 和 ( p - 1 ) * ( q - 1 )
互质。最后,利用Euclid 算法计算解密密钥d, 满足
e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )
其中n和d也要互质。数e和
n是公钥,d是私钥。两个素数p和q不再需要,应该丢弃,不要让任
何人知道。 加密信息 m(二进制表示)时,首先把m分成等长数据
块 m1 ,m2,..., mi ,块长s,其中 2^s <= n, s 尽可能的大。对
应的密文是:
ci = mi^e ( mod n ) ( a )
解密时作如下计算:
mi = ci^d ( mod n ) ( b )
RSA 可用于数字签名,方案是用 ( a ) 式签名, ( b )
式验证。具体操作时考虑到安全性和 m信息量较大等因素,一般是先
作 HASH 运算。
RSA 的安全性。
RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理
论上的证明,因为没有证明破解RSA就一定需要作大数分解。假设存在
一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。目前,
RSA的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显
然的攻击方法。现在,人们已能分解140多个十进制位的大素数。因此,
模数n必须选大一些,因具体适用情况而定。
RSA的速度:
由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论
是软件还是硬件实现。速度一直是RSA的缺陷。一般来说只用于少量数据
加密。
RSA的选择密文攻击:
RSA在选择密文攻击面前很脆弱。一般攻击者是将某一信息作一下伪装
(Blind),让拥有私钥的实体签署。然后,经过计算就可得到它所想要的信
息。实际上,攻击利用的都是同一个弱点,即存在这样一个事实:乘幂保
留了输入的乘法结构:
( XM )^d = X^d *M^d mod n
前面已经提到,这个固有的问题来自于公钥密码系统的最有用的特征
--每个人都能使用公钥。但从算法上无法解决这一问题,主要措施有
两条:一条是采用好的公钥协议,保证工作过程中实体不对其他实体
任意产生的信息解密,不对自己一无所知的信息签名;另一条是决不
对陌生人送来的随机文档签名,签名时首先使用One-Way HashFunction
对文档作HASH处理,或同时使用不同的签名算法。在中提到了几种不
同类型的攻击方法。
RSA的公共模数攻击。
若系统中共有一个模数,只是不同的人拥有不同的e和d,系统将是危险
的。最普遍的情况是同一信息用不同的公钥加密,这些公钥共模而且互
质,那末该信息无需私钥就可得到恢复。设P为信息明文,两个加密密钥
为e1和e2,公共模数是n,则:
C1 = P^e1 mod n
C2 = P^e2 mod n
密码分析者知道n、e1、e2、C1和C2,就能得到P。
因为e1和e2互质,故用Euclidean算法能找到r和s,满足:
r * e1 + s * e2 = 1
假设r为负数,需再用Euclidean算法计算C1^(-1),则
( C1^(-1) )^(-r) * C2^s = P mod n
另外,还有其它几种利用公共模数攻击的方法。总之,如果知道给定模数
的一对e和d,一是有利于攻击者分解模数,一是有利于攻击者计算出其它
成对的e’和d’,而无需分解模数。解决办法只有一个,那就是不要共享
模数n。
RSA的小指数攻击。 有一种提高
RSA速度的建议是使公钥e取较小的值,这样会使加密变得易于实现,速度
有所提高。但这样作是不安全的,对付办法就是e和d都取较大的值。
RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。
RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各
种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。
RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难
度与大数分解难度等价。即RSA的重大缺陷是无法从理论上把握它的保密性
能如何,而且密码学界多数人士倾向于因子分解不是NPC问题。
RSA的缺点主要有:
A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次
一密。B)分组长度太大,为保证安全性,n 至少也要 600 bits
以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;
且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。
目前,SET(Secure Electronic Transaction)协议中要求CA采用2048比特长
的密钥,其他实体使用1024比特的密钥。
❺ 如何使用RSA签名给给信息加密和解密
java">{
publicstaticfinalStringKEY_ALGORITHM="RSA";
_ALGORITHM="MD5withRSA";
_KEY="RSAPublicKey";
_KEY="RSAPrivateKey";
/**
*用私钥对信息生成数字签名
*
*@paramdata
*加密数据
*@paramprivateKey
*私钥
*
*@return
*@throwsException
*/
publicstaticStringsign(byte[]data,StringprivateKey)throwsException{
//解密由base64编码的私钥
byte[]keyBytes=decryptBASE64(privateKey);
//构造PKCS8EncodedKeySpec对象
=newPKCS8EncodedKeySpec(keyBytes);
//KEY_ALGORITHM指定的加密算法
KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
//取私钥匙对象
PrivateKeypriKey=keyFactory.generatePrivate(pkcs8KeySpec);
//用私钥对信息生成数字签名
Signaturesignature=Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
returnencryptBASE64(signature.sign());
}
/**
*校验数字签名
*
*@paramdata
*加密数据
*@parampublicKey
*公钥
*@paramsign
*数字签名
*
*@return校验成功返回true失败返回false
*@throwsException
*
*/
publicstaticbooleanverify(byte[]data,StringpublicKey,Stringsign)
throwsException{
//解密由base64编码的公钥
byte[]keyBytes=decryptBASE64(publicKey);
//构造X509EncodedKeySpec对象
X509EncodedKeySpeckeySpec=newX509EncodedKeySpec(keyBytes);
//KEY_ALGORITHM指定的加密算法
KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
//取公钥匙对象
PublicKeypubKey=keyFactory.generatePublic(keySpec);
Signaturesignature=Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
//验证签名是否正常
returnsignature.verify(decryptBASE64(sign));
}
/**
*解密<br>
*用私钥解密
*
*@paramdata
*@paramkey
*@return
*@throwsException
*/
publicstaticbyte[]decryptByPrivateKey(byte[]data,Stringkey)
throwsException{
//对密钥解密
byte[]keyBytes=decryptBASE64(key);
//取得私钥
=newPKCS8EncodedKeySpec(keyBytes);
KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
KeyprivateKey=keyFactory.generatePrivate(pkcs8KeySpec);
//对数据解密
Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE,privateKey);
returncipher.doFinal(data);
}
/**
*解密<br>
*用私钥解密
*
*@paramdata
*@paramkey
*@return
*@throwsException
*/
publicstaticbyte[]decryptByPublicKey(byte[]data,Stringkey)
throwsException{
//对密钥解密
byte[]keyBytes=decryptBASE64(key);
//取得公钥
X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(keyBytes);
KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
KeypublicKey=keyFactory.generatePublic(x509KeySpec);
//对数据解密
Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE,publicKey);
returncipher.doFinal(data);
}
/**
*加密<br>
*用公钥加密
*
*@paramdata
*@paramkey
*@return
*@throwsException
*/
publicstaticbyte[]encryptByPublicKey(byte[]data,Stringkey)
throwsException{
//对公钥解密
byte[]keyBytes=decryptBASE64(key);
//取得公钥
X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(keyBytes);
KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
KeypublicKey=keyFactory.generatePublic(x509KeySpec);
//对数据加密
Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
returncipher.doFinal(data);
}
/**
*加密<br>
*用私钥加密
*
*@paramdata
*@paramkey
*@return
*@throwsException
*/
publicstaticbyte[]encryptByPrivateKey(byte[]data,Stringkey)
throwsException{
//对密钥解密
byte[]keyBytes=decryptBASE64(key);
//取得私钥
=newPKCS8EncodedKeySpec(keyBytes);
KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
KeyprivateKey=keyFactory.generatePrivate(pkcs8KeySpec);
//对数据加密
Ciphercipher=Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
returncipher.doFinal(data);
}
/**
*取得私钥
*
*@paramkeyMap
*@return
*@throwsException
*/
(Map<String,Object>keyMap)
throwsException{
Keykey=(Key)keyMap.get(PRIVATE_KEY);
returnencryptBASE64(key.getEncoded());
}
/**
*取得公钥
*
*@paramkeyMap
*@return
*@throwsException
*/
(Map<String,Object>keyMap)
throwsException{
Keykey=(Key)keyMap.get(PUBLIC_KEY);
returnencryptBASE64(key.getEncoded());
}
/**
*初始化密钥
*
*@return
*@throwsException
*/
publicstaticMap<String,Object>initKey()throwsException{
KeyPairGeneratorkeyPairGen=KeyPairGenerator
.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPairkeyPair=keyPairGen.generateKeyPair();
//公钥
RSAPublicKeypublicKey=(RSAPublicKey)keyPair.getPublic();
//私钥
RSAPrivateKeyprivateKey=(RSAPrivateKey)keyPair.getPrivate();
Map<String,Object>keyMap=newHashMap<String,Object>(2);
keyMap.put(PUBLIC_KEY,publicKey);
keyMap.put(PRIVATE_KEY,privateKey);
returnkeyMap;
}
}
❻ RSA加密与对称加密如何使用呢他们的混合应用又应该怎么用呢
RSA算法是第一个能同时用于加密和数字签名的算法。RSA算法能生成公私钥对。
假设A、B要通信,那么他们需要彼此知道对方的公钥,如果a向b发送信息,a先用自己的私钥对信息进行加密(即签名),然后用b的公钥进行加密。当
b收到消息时,先用自己的私钥进行解密,然后用a的公用进行解密(即验证签名),即可看到a发送的明文信息。
若是用对称密钥进行加密,则双方公用一个密钥,这个密钥需要绝对保密,不能让别人知道。a在向b发送信息前,先用这个密钥对信息进行加密,然后把加密的信息发送给b,之后再把密钥通过另一通道发送给b(要保证密钥传输的安全,不被其他人截获),b收到密文和密钥后,再用这个密钥进行解密,就可以得到原文。
若混合使用,假设还是a向b发送信息,a先用自己的私钥进行签名,然后再用双方公用的对称密钥(即会话密钥)进行加密,得到加密后的密文,然后用b的公钥对双方的会话密钥进行加密,得到加密的会话密钥,然后把加密的密文和加密的会话密钥一起发给b,b收到后先用自己的私钥对加密的会话密钥进行解密,得到会话密钥,再用会话密钥对加密的密文进行解密,得到签名的信息,然后用a的公钥对签名进行验证,便可得到原始信息。
❼ RSA算法加密
RSA加密算法是一种典型的非对称加密算法,它基于大数的因式分解数学难题,它也是应用最广泛的非对称加密算法,于1978年由美国麻省理工学院(MIT)的三位学着:Ron Rivest、Adi Shamir 和 Leonard Adleman 共同提出。
它的原理较为简单,假设有消息发送方A和消息接收方B,通过下面的几个步骤,就可以完成消息的加密传递:
消息发送方A在本地构建密钥对,公钥和私钥;
消息发送方A将产生的公钥发送给消息接收方B;
B向A发送数据时,通过公钥进行加密,A接收到数据后通过私钥进行解密,完成一次通信;
反之,A向B发送数据时,通过私钥对数据进行加密,B接收到数据后通过公钥进行解密。
由于公钥是消息发送方A暴露给消息接收方B的,所以这种方式也存在一定的安全隐患,如果公钥在数据传输过程中泄漏,则A通过私钥加密的数据就可能被解密。
如果要建立更安全的加密消息传递模型,需要消息发送方和消息接收方各构建一套密钥对,并分别将各自的公钥暴露给对方,在进行消息传递时,A通过B的公钥对数据加密,B接收到消息通过B的私钥进行解密,反之,B通过A的公钥进行加密,A接收到消息后通过A的私钥进行解密。
当然,这种方式可能存在数据传递被模拟的隐患,但可以通过数字签名等技术进行安全性的进一步提升。由于存在多次的非对称加解密,这种方式带来的效率问题也更加严重。
❽ 急!!!《密码学》问题! RSA数字签名中为什么不能先加密后签名
用RSA给别人发送一则信息,首先要用私钥加密签名,然后再用对方的公钥加密信息和签名,把消息发送给对方。
如果先加密后签名,那么签名在传播途中被人为地篡改,我们可以做个形象的比喻,本来鲍勃要发送给对方一则信息给艾丽丝,可是途中却被伊芙拦截,把签名稍加修改就成了自己发出去的一则信息了,那么鲍勃就不知道这是谁发出的信息了。
❾ 密码学问题 为什么RSA数字签名一定要先签名、后加密我是初学者,谢谢!!!
我是这么觉得:
签名的一个目的是:防止签名双方抵赖。
如果先加密的话,到时候他有可能不认账。
而且,特别是针对RSA签名算法,有一种专门针对先加密后签名的攻击。为了防止这种攻击,推荐采用先签名后加密。
这种攻击方法为:
假设签名者A用先加密后签名的方法把消息x发给B,他是先用B的公钥eb对x加密,然后用自己的私钥da签名,设A的模数为na,B的为nb,那么,A发给B的密文为:
(x^eb
mod
nb)^da
mod
na
如果B不诚实,那么B可能伪造A的签名。谎称收到的是x1.因为nb是B的模数,所以B知道nb的分解,于是可以计算模nb的离散对数。
(x1)^k=x
mod
nb
之后,B再公布他的新公钥。然后宣布收到的是x1不是x。