❶ 求RSA演算法的源代碼(c語言)
這個是我幫個朋友寫的,寫的時候發現其實這個沒那麼復雜,不過,時間復雜度要高於那些成型了的,為人所熟知的rsa演算法的其他語言實現.
#include
int
candp(int
a,int
b,int
c)
{
int
r=1;
b=b+1;
while(b!=1)
{
r=r*a;
r=r%c;
b--;
}
printf("%d",r);
return
r;
}
void
main()
{
int
p,q,e,d,m,n,t,c,r;
char
s;
{printf("input
the
p:\n");
scanf("%d\n",&p);
printf("input
the
q:\n");
scanf("%d%d\n",&p);
n=p*q;
printf("so,the
n
is
%3d\n",n);
t=(p-1)*(q-1);
printf("so,the
t
is
%3d\n",t);
printf("please
intput
the
e:\n");
scanf("%d",&e);
if(e<1||e>t)
{printf("e
is
error,please
input
again;");
scanf("%d",&e);}
d=1;
while
(((e*d)%t)!=1)
d++;
printf("then
caculate
out
that
the
d
is
%5d",d);
printf("if
you
want
to
konw
the
cipher
please
input
1;\n
if
you
want
to
konw
the
plain
please
input
2;\n");
scanf("%d",&r);
if(r==1)
{
printf("input
the
m
:"
);/*輸入要加密的明文數字*/
scanf("%d\n",&m);
c=candp(m,e,n);
printf("so
,the
cipher
is
%4d",c);}
if(r==2)
{
printf("input
the
c
:"
);/*輸入要解密的密文數字*/
scanf("%d\n",&c);
m=candp(c,d,n);
printf("so
,the
cipher
is
%4d\n",m);
printf("do
you
want
to
use
this
programe:yes
or
no");
scanf("%s",&s);
}while(s=='y');
}
}
❷ java RSA演算法實現256位密鑰怎麼做
【下載實例】本文介紹RSA2加密與解密,RSA2是RSA的加強版本,在密鑰長度上採用2048, RSA2比RSA更安全,更可靠, 本人的另一篇文章RSA已經發表,有想了解的可以點開下面的RSA文章
❸ rsa演算法中p,q,n,e,d一般大小都為多少啊
RSA遭受攻擊的很多情況是因為演算法實現的一些細節上的漏洞所導致的,所以在使用RSA演算法構造密碼系統時,為保證安全,在生成大素數的基礎上,還必須認真仔細選擇參數,防止漏洞的形成。根據RSA加解密過程,其主要參數有三個:模數N,加密密鑰e,解密密鑰d。
3.4.1 模數N的確定
雖然迄今人們無法證明,破解RSA系統等於對N因子分解,但一般相信RSA系統的安全性等同於因子分解,即:若能分解因子N,即能攻破RSA系統,若能攻破RSA系統,即能分解因子Ⅳ。因此,在使用RSA系統時,對於模數N的選擇非常重要。在RSA演算法中,通過產生的兩個大素數p和q相乘得到模數N,而後分別通過對它們的數學運算得到密鑰對。由此,分解模數N得到p和q是最顯然的攻擊方法,當然也是最困難的方法,如果模數N被分解,攻擊者利用得到的P和q便可計算出,進而通過公開密鑰e由解密密鑰d,則RSA體制立刻被攻破。相當一部分的對RSA的攻擊就是試圖分解模數N,選擇合適的N是實現RSA演算法並防止漏洞的重要環節。一般地,模數N的確定可以遵循以下幾個原則:
①p和q之差要大。
當p和q相差很小時,在已知n的情況下,可假定二者的平均值為,然後利用,若等式右邊可開方,則得到及,即N被分解。
②p-1和q-1的最大公因子應很小。
③p和q必須為強素數。
一素數p如果滿足:
條件一:存在兩個大素數,,使得|p-1且|p+1;
條件二:存在四個大素數,,,使得。則此素數為強素數。其中,,,稱為3級的素數,,稱為2級的素數,p則稱為1級的素數,很明顯地,任何素數均為3級的素數。只有兩個強素數的積所構成的N,其因子分解才是較難的數學問題。
④p和q應大到使得因子分解N為計算上不可能。
RSA的安全性依賴於大數的因子分解,若能因子分解模數N,則RSA即被攻破,因此模數N必須足夠大直至因子分解N在計算上不可行。因子分解問題為密碼學最基本的難題之一,如今,因子分解的演算法已有長足的進步,但仍不足以說明RSA可破解。為保證安全性,實際應用中所選擇的素數P和拿至少應該為300位以上的二進制數,相應的模數N將是600位以上的二進制數。
目前,SET(Secure Electronic Transaction)協議中要求CA採用2048比特長的密鑰,其他實體使用1024比特的密鑰。隨著計算能力的提高和分布式運算的發展,安全密鑰的長度將是動態增長的。
Jadith Moore給出了使用RSA時有關模數的一些限制:
①若給定模數的一個加/解密密鑰指數對已知,攻擊者就能分解這個模數。
②若給定模數的一個加/解密密鑰指數對已知,攻擊者無需分解模數Ⅳ就可以計算出別的加/解密密鑰指數對。
③在通信網路中,利用RSA的協議不應該使用公共模數。
④消息應該用隨機數填充以避免對加密指數的攻擊。
3.4.2 e的選取原則
在RSA演算法中,e和互質的條件容易滿足,如果選擇較小的e,則加、解密的速度加快,也便於存儲,但會導致安全問題。
一般地,e的選取有如下原則:
①e不能夠太小。在RSA系統中,每人的公開密鑰P只要滿足即可,也即e可以任意選擇,為了減少加密運算時間,很多人採用盡可能小的e值,如3。但是已經證明低指數將會導致安全問題,故此,一般選擇e為16位的素數,可以有效防止攻擊,又有較快速度。
②e應選擇使其在的階為最大。即存在i,使得,
可以有效抗擊攻擊。
3.4.3 d的選取原則
一般地,私密密鑰d要大於。在許多應用場合,常希望使用位數較短的密鑰以降低解密或簽名的時間。例如IC卡應用中,IC卡CPU的計算能力遠低於計算機主機。長度較短的d可以減少IC卡的解密或簽名時間,而讓較復雜的加密或驗證預算(e長度較長)由快速的計算機主機運行。一個直接的問題就是:解密密鑰d的長度減少是否會造成安全性的降低?很明顯地,若d的長度太
小,則可以利用已知明文M加密後得,再直接猜測d,求出是否等於M。若是,則猜測J下確,否則繼續猜測。若d的長度過小,則猜測的空間變小,猜中的可能性加大,已有證明當時,可以由連分式演算法在多項式時間內求出d值。因此其長度不能過小。
❹ 求正確的RSA加密解密演算法C語言的,多謝。
//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;
}
❺ 「青鋒愛分享」Springboot+python之RSA加解密方案(RSA深入)二
本篇文章要結合上一節文章一起看。
青鋒愛分享-RSA-Springboot+Python整合
碼雲搜索: 青鋒 會有驚喜哦哦。
通過python生成的公鑰私鑰 格式PKCS1 。
生成pem格式如下:
私鑰頭(-----BEGIN RSA PRIVATE KEY-----)
私鑰尾(-----END RSA PRIVATE KEY-----)
我需要將此私鑰轉換為DER編碼的PKCS8未加密格式,以便與java伺服器代碼一起使用,特別是PKCS8EncodedKeySpec。我已經試過使用rsa和pkcs8命令的OpenSSL,如果有更簡單的辦法,沒有特別需要使用openssl。
RSA私鑰格式PKCS1和PKCS8相互轉換
RSA公鑰格式PKCS1和PKCS8相互轉換
以下轉換基於openssl命令的操作;
執行:openssl genrsa -out private.pem 1024
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDlLm5++/wwSfq5KfY
H8q1AO/
Uo4OMcmoSz3IAp/7//ewIDAQAB
AoGBAJkMdvF+i9Kzc6YqMC0rfQJ3Zs+vFOtsbmQVAMnQ8JWBCJ1O8d/c60wRQgyb
lFCyO7VXOmoIJqX/Jr2aER8bFtG+
lOdOay7TkE45X/Wc7K9iZs2uuB7sylIvK/HVxxit6FGePa4RAkEA9e+VoAbxBv78
HyxRcStW+
n0UxgT55MPXWGdMRXUUOCNnMilaw/
HvK0IW3zpOgf/+/W565ROI/fjkR1qCD
rZJeHgqMWDlIUuR9+BdBAkAI8+
puQxMonRWTN+
-----END RSA PRIVATE KEY-----
執行:openssl pkcs8 -topk8 -inform PEM -in private.pem -outform pem -nocrypt -out pkcs8.pem
-----BEGIN PRIVATE KEY-----
+n
yHOOfV+XbBPsC7aWblIS3Pqv7/DBJ+/T
uaDSVA4K8Tmx22YC8PZ7HfAJ5/yVaaB2HmpSjg4xyahLPcgCn/v8WcxqDUh6VJ92
/
Q3fic/
+
nt0qVQJAOmMZ67caK+YHZ0M3Rp3adQgF+
//6OHlRQIElgect4wb
CbtfXWu9AfXNbTlXH39bnrlE4j9+
Yt1Zx5df0+
HLU0VEwSQa7rvmY=
-----END PRIVATE KEY-----
執行:openssl rsa -in pkcs8.pem -out pkcs1.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDlLm5++/wwSfq5KfY
H8q1AO/
Uo4OMcmoSz3IAp/7//ewIDAQAB
AoGBAJkMdvF+i9Kzc6YqMC0rfQJ3Zs+vFOtsbmQVAMnQ8JWBCJ1O8d/c60wRQgyb
lFCyO7VXOmoIJqX/Jr2aER8bFtG+
lOdOay7TkE45X/Wc7K9iZs2uuB7sylIvK/HVxxit6FGePa4RAkEA9e+VoAbxBv78
HyxRcStW+
n0UxgT55MPXWGdMRXUUOCNnMilaw/
HvK0IW3zpOgf/+/W565ROI/fjkR1qCD
rZJeHgqMWDlIUuR9+BdBAkAI8+
puQxMonRWTN+
-----END RSA PRIVATE KEY-----
可以看出結果和1是一致的;
執行:openssl rsa -in private.pem -pubout -out public.pem
-----BEGIN PUBLIC KEY-----
+Kosybacfp8hzjn1fl2wT
7Au2lm5SEtz6r+/wwSfq5KfYH8q1AO/
/7/FnMag1IelSfdronPBDxazp6
NUmQZITsYK6CsEl/ewIDAQAB
-----END PUBLIC KEY-----
5. 從pkcs8私鑰中生成pkcs8公鑰
執行:openssl rsa -in pkcs8.pem -pubout -out public_pkcs8.pem
-----BEGIN PUBLIC KEY-----
+Kosybacfp8hzjn1fl2wT
7Au2lm5SEtz6r+/wwSfq5KfYH8q1AO/
/7/FnMag1IelSfdronPBDxazp6
NUmQZITsYK6CsEl/ewIDAQAB
-----END PUBLIC KEY-----
可以看出結果和4是一樣的;
執行:openssl rsa -pubin -in public.pem -RSAPublicKey_out
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAOUubn4qizJtpx+nyHOOfV+XbBPsC7aWblIS3Pqv7/DBJ+rkp9gfyrUA
78L3YjASmmU1uupiY5dC7o/TuaDSVA4K8Tmx22YC8PZ7HfAJ5/yVaaB2HmpSjg4x
yahLPcgCn/=
-----END RSA PUBLIC KEY-----
openssl rsa -pubin -in public_pkcs8.pem -RSAPublicKey_out
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAOUubn4qizJtpx+nyHOOfV+XbBPsC7aWblIS3Pqv7/DBJ+rkp9gfyrUA
78L3YjASmmU1uupiY5dC7o/TuaDSVA4K8Tmx22YC8PZ7HfAJ5/yVaaB2HmpSjg4x
yahLPcgCn/=
-----END RSA PUBLIC KEY-----
可以看出轉換的結果是一致的;
執行:openssl rsa -RSAPublicKey_in -in pub_pkcs1.pem -pubout
-----BEGIN PUBLIC KEY-----
+Kosybacfp8hzjn1fl2wT
7Au2lm5SEtz6r+/wwSfq5KfYH8q1AO/
/7/FnMag1IelSfdronPBDxazp6
NUmQZITsYK6CsEl/ewIDAQAB
-----END PUBLIC KEY-----
可以看到和上面4,5的結果是一致的;
最後一點:
iOS上用的是pkcs8格式的公鑰
openssl用的是pkcs1格式的公鑰
知道私鑰以後是可以導出公鑰的,所以私鑰一定要保證安全
知道公鑰不可以導出私鑰
解決方案針對是window電腦。
配置:SystemRoot/ System32 環境變數。
1、郵件我的電腦-選擇下【屬性】。
2、選擇高級系統設置
3、選擇【高級】-【環境變數】
4、雙擊打開path,進行編輯
5、 接著我們在這名字後面加【;System32】就可以了。
安裝 Win64 OpenSSL,地址: http://slproweb.com/procts/Win32OpenSSL.html
下載後根據提示一步一步安裝,安裝完成後:
雙擊start.bat 啟動
❻ 如何實現用javascript實現rsa加解密
用javascript實現rsa加解密的實現方式是通過PKCS完成的。
1、整個定義的function
function pkcs1pad2(s,n) {
if(n < s.length + 11) { // TODO: fix for utf-8
alert("Message too long for RSA");
return null;
}
var ba = new Array();
var i = s.length - 1;
while(i >= 0 && n > 0) {
var c = s.charCodeAt(i--);
//UTF-8編碼為變長位元組,使用實際的位元組來記錄
if(c < 128) { // encode using utf-8
ba[--n] = c;
}
else if((c > 127) && (c < 2048)) {
ba[--n] = (c & 63) | 128;
ba[--n] = (c >> 6) | 192;
}
else {
ba[--n] = (c & 63) | 128;
ba[--n] = ((c >> 6) & 63) | 128;
ba[--n] = (c >> 12) | 224;
}
}
//實際輸入拼裝結束,將下一位賦值為0標記結束
ba[--n] = 0;
var rng = new SecureRandom();
var x = new Array();
//拼接隨機非0位元組
while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
//這兩位做簡單的校驗
ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);
}
該方法中對UTF-8字元進行了兼容,並且在拼裝完實際輸入的字元後,還拼裝了隨機的位元組,使用拼裝後的字元串去加密。由於每次拼裝的結果是隨機的,這樣每次加密後的密文都不同。
2、調用方法:;
function RSAEncrypt(text) {
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
if(m == null) return null;
var c = this.doPublic(m);
if(c == null) return null;
var h = c.toString(16);
if((h.length & 1) == 0) return h; else return "0" + h;
}
❼ 如何實現用javascript實現rsa加解密
服務端生成公鑰與私鑰,保存。
客戶端在請求到登錄頁面後,隨機生成一字元串。
後此隨機字元串作為密鑰加密密碼,再用從服務端獲取到的公鑰加密生成的隨機字元串
將此兩段密文傳入服務端,服務端用私鑰解出隨機字元串,再用此私鑰解出加密的密文。這其中有一個關鍵是解決服務端的公鑰,傳入客戶端,客戶端用此公鑰加密字元串後,後又能在服務端用私鑰解出。
步驟:
服務端的RSAJava實現:
/**
*
*/
packagecom.sunsoft.struts.util;
importjava.io.ByteArrayOutputStream;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.math.BigInteger;
importjava.security.KeyFactory;
importjava.security.KeyPair;
importjava.security.KeyPairGenerator;
importjava.security.NoSuchAlgorithmException;
importjava.security.PrivateKey;
importjava.security.PublicKey;
importjava.security.SecureRandom;
importjava.security.interfaces.RSAPrivateKey;
importjava.security.interfaces.RSAPublicKey;
importjava.security.spec.InvalidKeySpecException;
importjava.security.spec.RSAPrivateKeySpec;
importjava.security.spec.RSAPublicKeySpec;
importjavax.crypto.Cipher;/**
*RSA工具類。提供加密,解密,生成密鑰對等方法。
*需要到
下載bcprov-jdk14-123.jar。
*
*/
publicclassRSAUtil{
/**
**生成密鑰對*
*
*@returnKeyPair*
*@throwsEncryptException
*/
()throwsException{
try{
KeyPairGeneratorkeyPairGen=KeyPairGenerator.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
finalintKEY_SIZE=1024;//沒什麼好說的了,這個值關繫到塊加密的大小,可以更改,但是不要太大,否則效率會低
keyPairGen.initialize(KEY_SIZE,newSecureRandom());
KeyPairkeyPair=keyPairGen.generateKeyPair();
saveKeyPair(keyPair);
returnkeyPair;
}catch(Exceptione){
thrownewException(e.getMessage());
}
}
publicstaticKeyPairgetKeyPair()throwsException{
FileInputStreamfis=newFileInputStream("C:/RSAKey.txt");
ObjectInputStreamoos=newObjectInputStream(fis);
KeyPairkp=(KeyPair)oos.readObject();
oos.close();
fis.close();
returnkp;
}
publicstaticvoidsaveKeyPair(KeyPairkp)throwsException{
FileOutputStreamfos=newFileOutputStream("C:/RSAKey.txt");
ObjectOutputStreamoos=newObjectOutputStream(fos);
//生成密鑰
oos.writeObject(kp);
oos.close();
fos.close();
}
/**
**生成公鑰*
*
*@parammolus*
*@parampublicExponent*
*@returnRSAPublicKey*
*@throwsException
*/
(byte[]molus,
byte[]publicExponent)throwsException{
KeyFactorykeyFac=null;
try{
keyFac=KeyFactory.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
}catch(NoSuchAlgorithmExceptionex){
thrownewException(ex.getMessage());
}
RSAPublicKeySpecpubKeySpec=newRSAPublicKeySpec(newBigInteger(
molus),newBigInteger(publicExponent));
try{
return(RSAPublicKey)keyFac.generatePublic(pubKeySpec);
}catch(InvalidKeySpecExceptionex){
thrownewException(ex.getMessage());
}
}
/**
**生成私鑰*
*
*@parammolus*
*@paramprivateExponent*
*@returnRSAPrivateKey*
*@throwsException
*/
(byte[]molus,
byte[]privateExponent)throwsException{
KeyFactorykeyFac=null;
try{
keyFac=KeyFactory.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
}catch(NoSuchAlgorithmExceptionex){
thrownewException(ex.getMessage());
}
RSAPrivateKeySpecpriKeySpec=newRSAPrivateKeySpec(newBigInteger(
molus),newBigInteger(privateExponent));
try{
return(RSAPrivateKey)keyFac.generatePrivate(priKeySpec);
}catch(InvalidKeySpecExceptionex){
thrownewException(ex.getMessage());
}
}
/**
**加密*
*
*@paramkey
*加密的密鑰*
*@paramdata
*待加密的明文數據*
*@return加密後的數據*
*@throwsException
*/
publicstaticbyte[]encrypt(PublicKeypk,byte[]data)throwsException{
try{
Ciphercipher=Cipher.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE,pk);
intblockSize=cipher.getBlockSize();//獲得加密塊大小,如:加密前數據為128個byte,而key_size=1024
//加密塊大小為127
//byte,加密後為128個byte;因此共有2個加密塊,第一個127
//byte第二個為1個byte
intoutputSize=cipher.getOutputSize(data.length);//獲得加密塊加密後塊大小
intleavedSize=data.length%blockSize;
intblocksSize=leavedSize!=0?data.length/blockSize+1
:data.length/blockSize;
byte[]raw=newbyte[outputSize*blocksSize];
inti=0;
while(data.length-i*blockSize>0){
if(data.length-i*blockSize>blockSize)
cipher.doFinal(data,i*blockSize,blockSize,raw,i
*outputSize);
else
cipher.doFinal(data,i*blockSize,data.length-i
*blockSize,raw,i*outputSize);
//這裡面doUpdate方法不可用,查看源代碼後發現每次doUpdate後並沒有什麼實際動作除了把byte[]放到
//ByteArrayOutputStream中,而最後doFinal的時候才將所有的byte[]進行加密,可是到了此時加密塊大小很可能已經超出了
//OutputSize所以只好用dofinal方法。
i++;
}
returnraw;
}catch(Exceptione){
thrownewException(e.getMessage());
}
}
/**
**解密*
*
*@paramkey
*解密的密鑰*
*@paramraw
*已經加密的數據*
*@return解密後的明文*
*@throwsException
*/
publicstaticbyte[]decrypt(PrivateKeypk,byte[]raw)throwsException{
try{
Ciphercipher=Cipher.getInstance("RSA",
neworg.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE,pk);
intblockSize=cipher.getBlockSize();
ByteArrayOutputStreambout=newByteArrayOutputStream(64);
intj=0;
while(raw.length-j*blockSize>0){
bout.write(cipher.doFinal(raw,j*blockSize,blockSize));
j++;
}
returnbout.toByteArray();
}catch(Exceptione){
thrownewException(e.getMessage());
}
}
/**
***
*
*@paramargs*
*@throwsException
*/
publicstaticvoidmain(String[]args)throwsException{
RSAPublicKeyrsap=(RSAPublicKey)RSAUtil.generateKeyPair().getPublic();
Stringtest="helloworld";
byte[]en_test=encrypt(getKeyPair().getPublic(),test.getBytes());
byte[]de_test=decrypt(getKeyPair().getPrivate(),en_test);
System.out.println(newString(de_test));
}
}
測試頁面IndexAction.java:
/*
*GeneratedbyMyEclipseStruts
*Templatepath:templates/java/JavaClass.vtl
*/
packagecom.sunsoft.struts.action;
importjava.security.interfaces.RSAPrivateKey;
importjava.security.interfaces.RSAPublicKey;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.apache.struts.action.Action;
importorg.apache.struts.action.ActionForm;
importorg.apache.struts.action.ActionForward;
importorg.apache.struts.action.ActionMapping;
importcom.sunsoft.struts.util.RSAUtil;
/**
*MyEclipseStruts
*Creationdate:06-28-2008
*
*XDocletdefinition:
*@struts.actionvalidate="true"
*/
{
/*
*GeneratedMethods
*/
/**
*Methodexecute
*@parammapping
*@paramform
*@paramrequest
*@paramresponse
*@returnActionForward
*/
publicActionForwardexecute(ActionMappingmapping,ActionFormform,
HttpServletRequestrequest,HttpServletResponseresponse)throwsException{
RSAPublicKeyrsap=(RSAPublicKey)RSAUtil.getKeyPair().getPublic();
Stringmole=rsap.getMolus().toString(16);
Stringempoent=rsap.getPublicExponent().toString(16);
System.out.println("mole");
System.out.println(mole);
System.out.println("empoent");
System.out.println(empoent);
request.setAttribute("m",mole);
request.setAttribute("e",empoent);
returnmapping.findForward("login");
}
}
通過此action進入登錄頁面,並傳入公鑰的Molus 與PublicExponent的hex編碼形式。