MD5算法原理

MD5(單向散列算法) 的全稱是Message-Digest Algorithm 5(信息-摘要算法),經MD2、MD3和MD4發展而來。MD5算法的使用不需要支付任何版權費用。

???? MD5功能:
??? 輸入任意長度的信息,經過處理,輸出為128位的信息(數字指紋);
??? 不同的輸入得到的不同的結果(唯一性);
??? 根據128位的輸出結果不可能反推出輸入的信息(不可逆);?

???? MD5屬不屬于加密算法:
??? 認為不屬于的人是因為他們覺得不能從密文(散列值)反過來得到原文,即沒有解密算法,所以這部分人認為MD5只能屬于算法,不能稱為加密算法;
??? 認為屬于的人是因為他們覺得經過MD5處理后看不到原文,即已經將原文加密,所以認為MD5屬于加密算法;我個人支持后者。

???? MD5用途:
??? 1、 防止被篡改
??? 1)比如發送一個電子文檔,發送前,我先得到MD5的輸出結果a。然后在對方收到電子文檔后,對方也得到一個MD5的輸出結果b。如果a與b一樣就代表中途未被篡改。2)比如我提供文件下載,為了防止不法分子在安裝程序中添加木馬,我可以在網站上公布由安裝文件得到的MD5輸出結果。3)SVN在檢測文件是否在CheckOut后被修改過,也是用到了MD5.

??? 2、 防止直接看到明文
??? 現在很多網站在數據庫存儲用戶的密碼的時候都是存儲用戶密碼的MD5值。這樣就算不法分子得到數據庫的用戶密碼的MD5值,也無法知道用戶的密碼(其實這樣是不安全的,后面我會提到)。(比如在UNIX系統中用戶的密碼就是以MD5(或其它類似的算法)經加密后存儲在文件系統中。當用戶登錄的時候,系統把用戶輸入的密碼計算成MD5值,然后再去和保存在文件系統中的MD5值進行比較,進而確定輸入的密碼是否正確。通過這樣的步驟,系統在并不知道用戶密碼的明碼的情況下就可以確定用戶登錄系統的合法性。這不但可以避免用戶的密碼被具有系統管理員權限的用戶知道,而且還在一定程度上增加了密碼被破解的難度。)

??? 3、 防止抵賴(數字簽名):
??? 這需要一個第三方認證機構。例如A寫了一個文件,認證機構對此文件用MD5算法產生摘要信息并做好記錄。若以后A說這文件不是他寫的,權威機構只需對此文件重新產生摘要信息,然后跟記錄在冊的摘要信息進行比對,相同的話,就證明是A寫的了。這就是所謂的“數字簽名”。

??? ?MD5算法過程:
??? 對MD5算法簡要的敘述可以為:MD5以512位分組來處理輸入的信息,且每一分組又被劃分為16個32位子分組,經過了一系列的處理后,算法的輸出由四個32位分組組成,將這四個32位分組級聯后將生成一個128位散列值。

???? 第一步、填充:如果輸入信息的長度(bit)對512求余的結果不等于448,就需要填充使得對512求余的結果等于448。填充的方法是填充一個1和n個0。填充完后,信息的長度就為N*512+448(bit);

???? 第二步、記錄信息長度:用64位來存儲填充前信息長度。這64位加在第一步結果的后面,這樣信息長度就變為N*512+448+64=(N+1)*512位。

???? 第三步、裝入標準的幻數(四個整數):標準的幻數(物理順序)是(A=(01234567) 16 ,B=(89ABCDEF) 16 ,C=(FEDCBA98) 16 ,D=(76543210) 16 )。如果在程序中定義應該是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有點暈哈,其實想一想就明白了。

???? 第四步、四輪循環運算:循環的次數是分組的個數(N+1)?

???? 1)將每一512字節細分成16個小組,每個小組64位(8個字節)
?????
???? 2)先認識四個線性函數(&是與,|是或,~是非,^是異或)
??F(X,Y,Z)=(X&Y)|((~X)&Z)
??G(X,Y,Z)
=(X&Z)|(Y&(~Z))
??H(X,Y,Z)
=X^Y^Z
??I(X,Y,Z)
=Y^(X|(~Z))
????
??? 3)設Mj表示消息的第j個子分組(從0到15),<<<s表示循環左移s位,則四種操作為:
??FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s)
??GG(a,b,c,d,Mj,s,ti)表示a
=b+((a+G(b,c,d)+Mj+ti)<<<s)
??HH(a,b,c,d,Mj,s,ti)表示a
=b+((a+H(b,c,d)+Mj+ti)<<<s)
??II(a,b,c,d,Mj,s,ti)表示a
=b+((a+I(b,c,d)+Mj+ti)<<<s)

??? 4)四輪運算
第一輪
a
=FF(a,b,c,d,M0,7,0xd76aa478)
b
=FF(d,a,b,c,M1,12,0xe8c7b756)
c
=FF(c,d,a,b,M2,17,0x242070db)
d
=FF(b,c,d,a,M3,22,0xc1bdceee)
a
=FF(a,b,c,d,M4,7,0xf57c0faf)
b
=FF(d,a,b,c,M5,12,0x4787c62a)
c
=FF(c,d,a,b,M6,17,0xa8304613)
d
=FF(b,c,d,a,M7,22,0xfd469501)
a
=FF(a,b,c,d,M8,7,0x698098d8)
b
=FF(d,a,b,c,M9,12,0x8b44f7af)
c
=FF(c,d,a,b,M10,17,0xffff5bb1)
d
=FF(b,c,d,a,M11,22,0x895cd7be)
a
=FF(a,b,c,d,M12,7,0x6b901122)
b
=FF(d,a,b,c,M13,12,0xfd987193)
c
=FF(c,d,a,b,M14,17,0xa679438e)
d
=FF(b,c,d,a,M15,22,0x49b40821)

第二輪
a
=GG(a,b,c,d,M1,5,0xf61e2562)
b
=GG(d,a,b,c,M6,9,0xc040b340)
c
=GG(c,d,a,b,M11,14,0x265e5a51)
d
=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a
=GG(a,b,c,d,M5,5,0xd62f105d)
b
=GG(d,a,b,c,M10,9,0x02441453)
c
=GG(c,d,a,b,M15,14,0xd8a1e681)
d
=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a
=GG(a,b,c,d,M9,5,0x21e1cde6)
b
=GG(d,a,b,c,M14,9,0xc33707d6)
c
=GG(c,d,a,b,M3,14,0xf4d50d87)
d
=GG(b,c,d,a,M8,20,0x455a14ed)
a
=GG(a,b,c,d,M13,5,0xa9e3e905)
b
=GG(d,a,b,c,M2,9,0xfcefa3f8)
c
=GG(c,d,a,b,M7,14,0x676f02d9)
d
=GG(b,c,d,a,M12,20,0x8d2a4c8a)

第三輪
a
=HH(a,b,c,d,M5,4,0xfffa3942)
b
=HH(d,a,b,c,M8,11,0x8771f681)
c
=HH(c,d,a,b,M11,16,0x6d9d6122)
d
=HH(b,c,d,a,M14,23,0xfde5380c)
a
=HH(a,b,c,d,M1,4,0xa4beea44)
b
=HH(d,a,b,c,M4,11,0x4bdecfa9)
c
=HH(c,d,a,b,M7,16,0xf6bb4b60)
d
=HH(b,c,d,a,M10,23,0xbebfbc70)
a
=HH(a,b,c,d,M13,4,0x289b7ec6)
b
=HH(d,a,b,c,M0,11,0xeaa127fa)
c
=HH(c,d,a,b,M3,16,0xd4ef3085)
d
=HH(b,c,d,a,M6,23,0x04881d05)
a
=HH(a,b,c,d,M9,4,0xd9d4d039)
b
=HH(d,a,b,c,M12,11,0xe6db99e5)
c
=HH(c,d,a,b,M15,16,0x1fa27cf8)
d
=HH(b,c,d,a,M2,23,0xc4ac5665)

第四輪
a
=II(a,b,c,d,M0,6,0xf4292244)
b
=II(d,a,b,c,M7,10,0x432aff97)
c
=II(c,d,a,b,M14,15,0xab9423a7)
d
=II(b,c,d,a,M5,21,0xfc93a039)
a
=II(a,b,c,d,M12,6,0x655b59c3)
b
=II(d,a,b,c,M3,10,0x8f0ccc92)
c
=II(c,d,a,b,M10,15,0xffeff47d)
d
=II(b,c,d,a,M1,21,0x85845dd1)
a
=II(a,b,c,d,M8,6,0x6fa87e4f)
b
=II(d,a,b,c,M15,10,0xfe2ce6e0)
c
=II(c,d,a,b,M6,15,0xa3014314)
d
=II(b,c,d,a,M13,21,0x4e0811a1)
a
=II(a,b,c,d,M4,6,0xf7537e82)
b
=II(d,a,b,c,M11,10,0xbd3af235)
c
=II(c,d,a,b,M2,15,0x2ad7d2bb)
d
=II(b,c,d,a,M9,21,0xeb86d391)

??? 5)每輪循環后,將A,B,C,D分別加上a,b,c,d,然后進入下一循環。
?
??? 如果上面的過程用JAVA代碼來實現的話,代碼如下:?
package?woxingwosu;


/************************************************
?*?MD5?算法
?*?
@author?我行我素
?*?@Date?2007-07-01
************************************************
*/

public?class?MD5?{

????
static?final?String?hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
????
//標準的幻數
????private?static?final?long?A=0x67452301L;
????
private?static?final?long?B=0xefcdab89L;
????
private?static?final?long?C=0x98badcfeL;
????
private?static?final?long?D=0x10325476L;

????
????
//下面這些S11-S44實際上是一個4*4的矩陣,在四輪循環運算中用到
????static?final?int?S11?=?7;
????
static?final?int?S12?=?12;
????
static?final?int?S13?=?17;
????
static?final?int?S14?=?22;

????
static?final?int?S21?=?5;
????
static?final?int?S22?=?9;
????
static?final?int?S23?=?14;
????
static?final?int?S24?=?20;

????
static?final?int?S31?=?4;
????
static?final?int?S32?=?11;
????
static?final?int?S33?=?16;
????
static?final?int?S34?=?23;

????
static?final?int?S41?=?6;
????
static?final?int?S42?=?10;
????
static?final?int?S43?=?15;
????
static?final?int?S44?=?21;
????
????
//java不支持無符號的基本數據(unsigned)
????private?long?[]?result={A,B,C,D};//存儲hash結果,共4×32=128位,初始化值為(幻數的級聯)
????
????
public?static?void?main(String?[]args){
????????MD5?md
=new?MD5();
????????System.out.println(
"md5(abc)="+md.digest("abc"));
????}

????
????
private?String?digest(String?inputStr){
????????
byte?[]?inputBytes=inputStr.getBytes();
????????
int?byteLen=inputBytes.length;//長度(字節)
????????int?groupCount=0;//完整分組的個數
????????groupCount=byteLen/64;//每組512位(64字節)
????????long?[]groups=null;//每個小組(64字節)再細分后的16個小組(4字節)
????????
????????
//處理每一個完整?分組
????????for(int?step=0;step<groupCount;step++){
????????????groups
=divGroup(inputBytes,step*64);
????????????trans(groups);
//處理分組,核心算法
????????}

????????
????????
//處理完整分組后的尾巴
????????int?rest=byteLen%64;//512位分組后的余數
????????byte?[]?tempBytes=new?byte[64];
????????
if(rest<=56){
????????????
for(int?i=0;i<rest;i++)
????????????????tempBytes[i]
=inputBytes[byteLen-rest+i];
????????????
if(rest<56){
????????????????tempBytes[rest]
=(byte)(1<<7);
????????????????
for(int?i=1;i<56-rest;i++)
????????????????????tempBytes[rest
+i]=0;
????????????}

????????????
long?len=(long)(byteLen<<3);
????????????
for(int?i=0;i<8;i++){
????????????????tempBytes[
56+i]=(byte)(len&0xFFL);
????????????????len
=len>>8;
????????????}

????????????groups
=divGroup(tempBytes,0);
????????????trans(groups);
//處理分組
????????}
else{
????????????
for(int?i=0;i<rest;i++)
????????????????tempBytes[i]
=inputBytes[byteLen-rest+i];
????????????tempBytes[rest]
=(byte)(1<<7);
????????????
for(int?i=rest+1;i<64;i++)
????????????????tempBytes[i]
=0;
????????????groups
=divGroup(tempBytes,0);
????????????trans(groups);
//處理分組
????????????
????????????
for(int?i=0;i<56;i++)
????????????????tempBytes[i]
=0;
????????????
long?len=(long)(byteLen<<3);
????????????
for(int?i=0;i<8;i++){
????????????????tempBytes[
56+i]=(byte)(len&0xFFL);
????????????????len
=len>>8;
????????????}

????????????groups
=divGroup(tempBytes,0);
????????????trans(groups);
//處理分組
????????}

????????
????????
//將Hash值轉換成十六進制的字符串
????????String?resStr="";
????????
long?temp=0;
????????
for(int?i=0;i<4;i++){
????????????
for(int?j=0;j<4;j++){
????????????????temp
=result[i]&0x0FL;
????????????????String?a
=hexs[(int)(temp)];
????????????????result[i]
=result[i]>>4;
????????????????temp
=result[i]&0x0FL;
????????????????resStr
+=hexs[(int)(temp)]+a;
????????????????result[i]
=result[i]>>4;
????????????}

????????}

????????
return?resStr;
????}

????
????
/**
?????*?從inputBytes的index開始取512位,作為新的分組
?????*?將每一個512位的分組再細分成16個小組,每個小組64位(8個字節)
?????*?
@param?inputBytes
?????*?
@param?index
?????*?
@return
?????
*/

????
private?static?long[]?divGroup(byte[]?inputBytes,int?index){
????????
long?[]?temp=new?long[16];
????????
for(int?i=0;i<16;i++){
????????????temp[i]
=b2iu(inputBytes[4*i+index])|
????????????????(b2iu(inputBytes[
4*i+1+index]))<<8|
????????????????(b2iu(inputBytes[
4*i+2+index]))<<16|
????????????????(b2iu(inputBytes[
4*i+3+index]))<<24;
????????}

????????
return?temp;
????}

????
????
/**
?????*?這時不存在符號位(符號位存儲不再是代表正負),所以需要處理一下
?????*?
@param?b
?????*?
@return
?????
*/

????
public?static?long?b2iu(byte?b){
????????
return?b?<?0???b?&?0x7F?+?128?:?b;
?????}

????
????
/**
?????*?主要的操作,四輪循環
?????*?
@param?groups[]--每一個分組512位(64字節)
?????
*/

????
private?void?trans(long[]?groups)?{
????????
long?a?=?result[0],?b?=?result[1],?c?=?result[2],?d?=?result[3];
????????
/*第一輪*/
????????a?
=?FF(a,?b,?c,?d,?groups[0],?S11,?0xd76aa478L);?/*?1?*/
????????d?
=?FF(d,?a,?b,?c,?groups[1],?S12,?0xe8c7b756L);?/*?2?*/
????????c?
=?FF(c,?d,?a,?b,?groups[2],?S13,?0x242070dbL);?/*?3?*/
????????b?
=?FF(b,?c,?d,?a,?groups[3],?S14,?0xc1bdceeeL);?/*?4?*/
????????a?
=?FF(a,?b,?c,?d,?groups[4],?S11,?0xf57c0fafL);?/*?5?*/
????????d?
=?FF(d,?a,?b,?c,?groups[5],?S12,?0x4787c62aL);?/*?6?*/
????????c?
=?FF(c,?d,?a,?b,?groups[6],?S13,?0xa8304613L);?/*?7?*/
????????b?
=?FF(b,?c,?d,?a,?groups[7],?S14,?0xfd469501L);?/*?8?*/
????????a?
=?FF(a,?b,?c,?d,?groups[8],?S11,?0x698098d8L);?/*?9?*/
????????d?
=?FF(d,?a,?b,?c,?groups[9],?S12,?0x8b44f7afL);?/*?10?*/
????????c?
=?FF(c,?d,?a,?b,?groups[10],?S13,?0xffff5bb1L);?/*?11?*/
????????b?
=?FF(b,?c,?d,?a,?groups[11],?S14,?0x895cd7beL);?/*?12?*/
????????a?
=?FF(a,?b,?c,?d,?groups[12],?S11,?0x6b901122L);?/*?13?*/
????????d?
=?FF(d,?a,?b,?c,?groups[13],?S12,?0xfd987193L);?/*?14?*/
????????c?
=?FF(c,?d,?a,?b,?groups[14],?S13,?0xa679438eL);?/*?15?*/
????????b?
=?FF(b,?c,?d,?a,?groups[15],?S14,?0x49b40821L);?/*?16?*/

????????
/*第二輪*/
????????a?
=?GG(a,?b,?c,?d,?groups[1],?S21,?0xf61e2562L);?/*?17?*/
????????d?
=?GG(d,?a,?b,?c,?groups[6],?S22,?0xc040b340L);?/*?18?*/
????????c?
=?GG(c,?d,?a,?b,?groups[11],?S23,?0x265e5a51L);?/*?19?*/
????????b?
=?GG(b,?c,?d,?a,?groups[0],?S24,?0xe9b6c7aaL);?/*?20?*/
????????a?
=?GG(a,?b,?c,?d,?groups[5],?S21,?0xd62f105dL);?/*?21?*/
????????d?
=?GG(d,?a,?b,?c,?groups[10],?S22,?0x2441453L);?/*?22?*/
????????c?
=?GG(c,?d,?a,?b,?groups[15],?S23,?0xd8a1e681L);?/*?23?*/
????????b?
=?GG(b,?c,?d,?a,?groups[4],?S24,?0xe7d3fbc8L);?/*?24?*/
????????a?
=?GG(a,?b,?c,?d,?groups[9],?S21,?0x21e1cde6L);?/*?25?*/
????????d?
=?GG(d,?a,?b,?c,?groups[14],?S22,?0xc33707d6L);?/*?26?*/
????????c?
=?GG(c,?d,?a,?b,?groups[3],?S23,?0xf4d50d87L);?/*?27?*/
????????b?
=?GG(b,?c,?d,?a,?groups[8],?S24,?0x455a14edL);?/*?28?*/
????????a?
=?GG(a,?b,?c,?d,?groups[13],?S21,?0xa9e3e905L);?/*?29?*/
????????d?
=?GG(d,?a,?b,?c,?groups[2],?S22,?0xfcefa3f8L);?/*?30?*/
????????c?
=?GG(c,?d,?a,?b,?groups[7],?S23,?0x676f02d9L);?/*?31?*/
????????b?
=?GG(b,?c,?d,?a,?groups[12],?S24,?0x8d2a4c8aL);?/*?32?*/

????????
/*第三輪*/
????????a?
=?HH(a,?b,?c,?d,?groups[5],?S31,?0xfffa3942L);?/*?33?*/
????????d?
=?HH(d,?a,?b,?c,?groups[8],?S32,?0x8771f681L);?/*?34?*/
????????c?
=?HH(c,?d,?a,?b,?groups[11],?S33,?0x6d9d6122L);?/*?35?*/
????????b?
=?HH(b,?c,?d,?a,?groups[14],?S34,?0xfde5380cL);?/*?36?*/
????????a?
=?HH(a,?b,?c,?d,?groups[1],?S31,?0xa4beea44L);?/*?37?*/
????????d?
=?HH(d,?a,?b,?c,?groups[4],?S32,?0x4bdecfa9L);?/*?38?*/
????????c?
=?HH(c,?d,?a,?b,?groups[7],?S33,?0xf6bb4b60L);?/*?39?*/
????????b?
=?HH(b,?c,?d,?a,?groups[10],?S34,?0xbebfbc70L);?/*?40?*/
????????a?
=?HH(a,?b,?c,?d,?groups[13],?S31,?0x289b7ec6L);?/*?41?*/
????????d?
=?HH(d,?a,?b,?c,?groups[0],?S32,?0xeaa127faL);?/*?42?*/
????????c?
=?HH(c,?d,?a,?b,?groups[3],?S33,?0xd4ef3085L);?/*?43?*/
????????b?
=?HH(b,?c,?d,?a,?groups[6],?S34,?0x4881d05L);?/*?44?*/
????????a?
=?HH(a,?b,?c,?d,?groups[9],?S31,?0xd9d4d039L);?/*?45?*/
????????d?
=?HH(d,?a,?b,?c,?groups[12],?S32,?0xe6db99e5L);?/*?46?*/
????????c?
=?HH(c,?d,?a,?b,?groups[15],?S33,?0x1fa27cf8L);?/*?47?*/
????????b?
=?HH(b,?c,?d,?a,?groups[2],?S34,?0xc4ac5665L);?/*?48?*/

????????
/*第四輪*/
????????a?
=?II(a,?b,?c,?d,?groups[0],?S41,?0xf4292244L);?/*?49?*/
????????d?
=?II(d,?a,?b,?c,?groups[7],?S42,?0x432aff97L);?/*?50?*/
????????c?
=?II(c,?d,?a,?b,?groups[14],?S43,?0xab9423a7L);?/*?51?*/
????????b?
=?II(b,?c,?d,?a,?groups[5],?S44,?0xfc93a039L);?/*?52?*/
????????a?
=?II(a,?b,?c,?d,?groups[12],?S41,?0x655b59c3L);?/*?53?*/
????????d?
=?II(d,?a,?b,?c,?groups[3],?S42,?0x8f0ccc92L);?/*?54?*/
????????c?
=?II(c,?d,?a,?b,?groups[10],?S43,?0xffeff47dL);?/*?55?*/
????????b?
=?II(b,?c,?d,?a,?groups[1],?S44,?0x85845dd1L);?/*?56?*/
????????a?
=?II(a,?b,?c,?d,?groups[8],?S41,?0x6fa87e4fL);?/*?57?*/
????????d?
=?II(d,?a,?b,?c,?groups[15],?S42,?0xfe2ce6e0L);?/*?58?*/
????????c?
=?II(c,?d,?a,?b,?groups[6],?S43,?0xa3014314L);?/*?59?*/
????????b?
=?II(b,?c,?d,?a,?groups[13],?S44,?0x4e0811a1L);?/*?60?*/
????????a?
=?II(a,?b,?c,?d,?groups[4],?S41,?0xf7537e82L);?/*?61?*/
????????d?
=?II(d,?a,?b,?c,?groups[11],?S42,?0xbd3af235L);?/*?62?*/
????????c?
=?II(c,?d,?a,?b,?groups[2],?S43,?0x2ad7d2bbL);?/*?63?*/
????????b?
=?II(b,?c,?d,?a,?groups[9],?S44,?0xeb86d391L);?/*?64?*/

????????
/*加入到之前計算的結果當中*/
????????result[
0]?+=?a;
????????result[
1]?+=?b;
????????result[
2]?+=?c;
????????result[
3]?+=?d;
????????result[
0]=result[0]&0xFFFFFFFFL;
????????result[
1]=result[1]&0xFFFFFFFFL;
????????result[
2]=result[2]&0xFFFFFFFFL;
????????result[
3]=result[3]&0xFFFFFFFFL;
????}

????
????
/**
?????*?下面是處理要用到的線性函數
?????
*/

????
private?static?long?F(long?x,?long?y,?long?z)?{
????????
return?(x?&?y)?|?((~x)?&?z);
????}


????
private?static?long?G(long?x,?long?y,?long?z)?{
????????
return?(x?&?z)?|?(y?&?(~z));
????}


????
private?static?long?H(long?x,?long?y,?long?z)?{
????????
return?x?^?y?^?z;
????}


????
private?static?long?I(long?x,?long?y,?long?z)?{
????????
return?y?^?(x?|?(~z));
????}


????
private?static?long?FF(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
????????????
long?ac)?{
????????a?
+=?(F(b,?c,?d)&0xFFFFFFFFL)?+?x?+?ac;
????????a?
=?((a&0xFFFFFFFFL)<<?s)?|?((a&0xFFFFFFFFL)?>>>?(32?-?s));
????????a?
+=?b;
????????
return?(a&0xFFFFFFFFL);
????}


????
private?static?long?GG(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
????????????
long?ac)?{
????????a?
+=?(G(b,?c,?d)&0xFFFFFFFFL)?+?x?+?ac;
????????a?
=?((a&0xFFFFFFFFL)?<<?s)?|?((a&0xFFFFFFFFL)?>>>?(32?-?s));
????????a?
+=?b;
????????
return?(a&0xFFFFFFFFL);
????}


????
private?static?long?HH(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
????????????
long?ac)?{
????????a?
+=?(H(b,?c,?d)&0xFFFFFFFFL)?+?x?+?ac;
????????a?
=?((a&0xFFFFFFFFL)?<<?s)?|?((a&0xFFFFFFFFL)?>>>?(32?-?s));
????????a?
+=?b;
????????
return?(a&0xFFFFFFFFL);
????}


????
private?static?long?II(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
????????????
long?ac)?{
????????a?
+=?(I(b,?c,?d)&0xFFFFFFFFL)?+?x?+?ac;
????????a?
=?((a&0xFFFFFFFFL)?<<?s)?|?((a&0xFFFFFFFFL)?>>>?(32?-?s));
????????a?
+=?b;
????????
return?(a&0xFFFFFFFFL);
????}

}

MD5安全性:
??? 普遍認為MD5是很安全,因為暴力破解的時間是一般人無法接受的。實際上如果把用戶的密碼MD5處理后再存儲到數據庫,其實是很不安全的。因為用戶的密碼是比較短的,而且很多用戶的密碼都使用生日,手機號碼,身份證號碼,電話號碼等等。或者使用常用的一些吉利的數字,或者某個英文單詞。如果我把常用的密碼先MD5處理,把數據存儲起來,然后再跟你的MD5結果匹配,這時我就有可能得到明文。比如某個MD5破解網站 http://www.cmd5.com/default.aspx ,我把其網站下的公告復制如下
??md5破解、動網論壇密碼破解等不再需要用窮舉法,本站共有md5記錄235億條,還在不斷增長中,已包含10位及10位以下數字、7位字母、部分7位字母+數字,全部6位及以下字母加數字等組合,并針對國內用戶做了大量優化,例如已經包含所有手機號碼、全國部分大中城市固定電話號碼、百家姓、常用拼音等大量組合,另加入了某大型網站真實會員密碼數據10萬條。本站數據量大,查詢速度快,同時支持16位及32位密碼查詢。通過對10萬會員的真實動網論壇樣本數據的測試,本站對于動網論壇密碼的命中率達到83%
??本站4T的硬盤已經上線,正在生成數據,預計需要2個月左右時間,到時候本站能查詢到12位數字和9位字母。
?? 你可以用你的生日,手機號碼去測試一下。
???我覺得只需要將上面我寫的MD5的標準幻數A,B,C,D的值修改一下,修改后也不是MD5算法了,因為不能保證唯一性。這樣就算別人得到32位的值,他如果不知道幻數的值是無法還原明文的。就算得到了幻數,也是很難破解的。

????? JAVA實現MD5
??? 在java中實現MD5是很簡單的,在包java.security有個類MessageDigest。官方文檔如下
????MessageDigest?類為應用程序提供信息摘要算法的功能,如?MD5?或?SHA?算法。信息摘要是安全的單向哈希函數,它接收任意大小的數據,輸出固定長度的哈希值。?

????MessageDigest?對象開始被初始化。該對象通過使用?update?方法處理數據。任何時候都可以調用?reset?方法重置摘要。一旦所有需要更新的數據都已經被更新了,應該調用?digest?方法之一完成哈希計算。?

????對于給定數量的更新數據,digest?方法只能被調用一次。digest?被調用后,MessageDigest?對象被重新設置成其初始狀態。
?? 使用MessageDigest很簡單,例如?
package?woxingwosu;
/************************************************
?*?MD5?算法
?*?@author?我行我素
?*?@Date?2007-07-06
************************************************
*/

import?java.security.MessageDigest;

public?class?MyMD5?{

????
static?char[]?hex?=?{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};?
????
public?static?void?main(String[]?args)?{
????????
try{
????????????MessageDigest?md5?
=?MessageDigest.getInstance("MD5");//申明使用MD5算法
????????????md5.update("a".getBytes());//
????????????System.out.println("md5(a)="+byte2str(md5.digest()));
????????????md5.update(
"a".getBytes());
????????????md5.update(
"bc".getBytes());
????????????System.
out.println("md5(abc)="+byte2str(md5.digest()));
????????}
catch(Exception?e){
????????????e.printStackTrace();
????????}

????}

????
????
/**
?????*?將字節數組轉換成十六進制字符串
?????*?@param?bytes
?????*?@return
?????
*/

????
private?static?String?byte2str(byte?[]bytes){
????????
int?len?=?bytes.length;???
????????StringBuffer?result?
=?new?StringBuffer();????
????????
for?(int?i?=?0;?i?<?len;?i++)?{???
????????????
byte?byte0?=?bytes[i];???
????????????result.append(hex[byte0?
>>>?4?&?0xf]);???
????????????result.append(hex[byte0?
&?0xf]);???
????????}

????????
return?result.toString();
????}

}
?
?? 另外附上其他版本的MD5算法的實現( 來自網絡 )
??? 1) JS版的MD5 (調用方法:md5(明文))
/*
?*?A?JavaScript?implementation?of?the?RSA?Data?Security,?Inc.?MD5?Message
?*?Digest?Algorithm,?as?defined?in?RFC?1321.
?*?Version?2.1?Copyright?(C)?Paul?Johnston?1999?-?2002.
?*?Other?contributors:?Greg?Holt,?Andrew?Kepert,?Ydnar,?Lostinet
?*?Distributed?under?the?BSD?License
?*?See?http://pajhome.org.uk/crypt/md5?for?more?info.
?
*/


/*
?*?Configurable?variables.?You?may?need?to?tweak?these?to?be?compatible?with
?*?the?server-side,?but?the?defaults?work?in?most?cases.
?
*/

var?hexcase?=?1;??/*?hex?output?format.?0?-?lowercase;?1?-?uppercase????????*/
var?b64pad??=?"";?/*?base-64?pad?character.?"="?for?strict?RFC?compliance???*/
var?chrsz???=?8;??/*?bits?per?input?character.?8?-?ASCII;?16?-?Unicode??????*/

/*
?*?These?are?the?functions?you'll?usually?want?to?call
?*?They?take?string?arguments?and?return?either?hex?or?base-64?encoded?strings
?
*/

function?hex_md5(s){?return?binl2hex(core_md5(str2binl(s),?s.length?*?chrsz));}
function?str_md5(s){?return?binl2str(core_md5(str2binl(s),?s.length?*?chrsz));}
function?hex_hmac_md5(key,?data)?{?return?binl2hex(core_hmac_md5(key,?data));?}
function?str_hmac_md5(key,?data)?{?return?binl2str(core_hmac_md5(key,?data));?}

/*
?*?Calculate?the?MD5?of?an?array?of?little-endian?words,?and?a?bit?length
?
*/

function?core_md5(x,?len)
{
??
/*?append?padding?*/
??x[len?
>>?5]?|=?0x80?<<?((len)?%?32);
??x[(((len?
+?64)?>>>?9)?<<?4)?+?14]?=?len;

??
var?a?=??1732584193;
??
var?b?=?-271733879;
??
var?c?=?-1732584194;
??
var?d?=??271733878;

??
for(var?i?=?0;?i?<?x.length;?i?+=?16)
??
{
????
var?olda?=?a;
????
var?oldb?=?b;
????
var?oldc?=?c;
????
var?oldd?=?d;

????a?
=?md5_ff(a,?b,?c,?d,?x[i+?0],?7?,?-680876936);
????d?
=?md5_ff(d,?a,?b,?c,?x[i+?1],?12,?-389564586);
????c?
=?md5_ff(c,?d,?a,?b,?x[i+?2],?17,??606105819);
????b?
=?md5_ff(b,?c,?d,?a,?x[i+?3],?22,?-1044525330);
????a?
=?md5_ff(a,?b,?c,?d,?x[i+?4],?7?,?-176418897);
????d?
=?md5_ff(d,?a,?b,?c,?x[i+?5],?12,??1200080426);
????c?
=?md5_ff(c,?d,?a,?b,?x[i+?6],?17,?-1473231341);
????b?
=?md5_ff(b,?c,?d,?a,?x[i+?7],?22,?-45705983);
????a?
=?md5_ff(a,?b,?c,?d,?x[i+?8],?7?,??1770035416);
????d?
=?md5_ff(d,?a,?b,?c,?x[i+?9],?12,?-1958414417);
????c?
=?md5_ff(c,?d,?a,?b,?x[i+10],?17,?-42063);
????b?
=?md5_ff(b,?c,?d,?a,?x[i+11],?22,?-1990404162);
????a?
=?md5_ff(a,?b,?c,?d,?x[i+12],?7?,??1804603682);
????d?
=?md5_ff(d,?a,?b,?c,?x[i+13],?12,?-40341101);
????c?
=?md5_ff(c,?d,?a,?b,?x[i+14],?17,?-1502002290);
????b?
=?md5_ff(b,?c,?d,?a,?x[i+15],?22,??1236535329);

????a?
=?md5_gg(a,?b,?c,?d,?x[i+?1],?5?,?-165796510);
????d?
=?md5_gg(d,?a,?b,?c,?x[i+?6],?9?,?-1069501632);
????c?
=?md5_gg(c,?d,?a,?b,?x[i+11],?14,??643717713);
????b?
=?md5_gg(b,?c,?d,?a,?x[i+?0],?20,?-373897302);
????a?
=?md5_gg(a,?b,?c,?d,?x[i+?5],?5?,?-701558691);
????d?
=?md5_gg(d,?a,?b,?c,?x[i+10],?9?,??38016083);
????c?
=?md5_gg(c,?d,?a,?b,?x[i+15],?14,?-660478335);
????b?
=?md5_gg(b,?c,?d,?a,?x[i+?4],?20,?-405537848);
????a?
=?md5_gg(a,?b,?c,?d,?x[i+?9],?5?,??568446438);
????d?
=?md5_gg(d,?a,?b,?c,?x[i+14],?9?,?-1019803690);
????c?
=?md5_gg(c,?d,?a,?b,?x[i+?3],?14,?-187363961);
????b?
=?md5_gg(b,?c,?d,?a,?x[i+?8],?20,??1163531501);
????a?
=?md5_gg(a,?b,?c,?d,?x[i+13],?5?,?-1444681467);
????d?
=?md5_gg(d,?a,?b,?c,?x[i+?2],?9?,?-51403784);
????c?
=?md5_gg(c,?d,?a,?b,?x[i+?7],?14,??1735328473);
????b?
=?md5_gg(b,?c,?d,?a,?x[i+12],?20,?-1926607734);

????a?
=?md5_hh(a,?b,?c,?d,?x[i+?5],?4?,?-378558);
????d?
=?md5_hh(d,?a,?b,?c,?x[i+?8],?11,?-2022574463);
????c?
=?md5_hh(c,?d,?a,?b,?x[i+11],?16,??1839030562);
????b?
=?md5_hh(b,?c,?d,?a,?x[i+14],?23,?-35309556);
????a?
=?md5_hh(a,?b,?c,?d,?x[i+?1],?4?,?-1530992060);
????d?
=?md5_hh(d,?a,?b,?c,?x[i+?4],?11,??1272893353);
????c?
=?md5_hh(c,?d,?a,?b,?x[i+?7],?16,?-155497632);
????b?
=?md5_hh(b,?c,?d,?a,?x[i+10],?23,?-1094730640);
????a?
=?md5_hh(a,?b,?c,?d,?x[i+13],?4?,??681279174);
????d?
=?md5_hh(d,?a,?b,?c,?x[i+?0],?11,?-358537222);
????c?
=?md5_hh(c,?d,?a,?b,?x[i+?3],?16,?-722521979);
????b?
=?md5_hh(b,?c,?d,?a,?x[i+?6],?23,??76029189);
????a?
=?md5_hh(a,?b,?c,?d,?x[i+?9],?4?,?-640364487);
????d?
=?md5_hh(d,?a,?b,?c,?x[i+12],?11,?-421815835);
????c?
=?md5_hh(c,?d,?a,?b,?x[i+15],?16,??530742520);
????b?
=?md5_hh(b,?c,?d,?a,?x[i+?2],?23,?-995338651);

????a?
=?md5_ii(a,?b,?c,?d,?x[i+?0],?6?,?-198630844);
????d?
=?md5_ii(d,?a,?b,?c,?x[i+?7],?10,??1126891415);
????c?
=?md5_ii(c,?d,?a,?b,?x[i+14],?15,?-1416354905);
????b?
=?md5_ii(b,?c,?d,?a,?x[i+?5],?21,?-57434055);
????a?
=?md5_ii(a,?b,?c,?d,?x[i+12],?6?,??1700485571);
????d?
=?md5_ii(d,?a,?b,?c,?x[i+?3],?10,?-1894986606);
????c?
=?md5_ii(c,?d,?a,?b,?x[i+10],?15,?-1051523);
????b?
=?md5_ii(b,?c,?d,?a,?x[i+?1],?21,?-2054922799);
????a?
=?md5_ii(a,?b,?c,?d,?x[i+?8],?6?,??1873313359);
????d?
=?md5_ii(d,?a,?b,?c,?x[i+15],?10,?-30611744);
????c?
=?md5_ii(c,?d,?a,?b,?x[i+?6],?15,?-1560198380);
????b?
=?md5_ii(b,?c,?d,?a,?x[i+13],?21,??1309151649);
????a?
=?md5_ii(a,?b,?c,?d,?x[i+?4],?6?,?-145523070);
????d?
=?md5_ii(d,?a,?b,?c,?x[i+11],?10,?-1120210379);
????c?
=?md5_ii(c,?d,?a,?b,?x[i+?2],?15,??718787259);
????b?
=?md5_ii(b,?c,?d,?a,?x[i+?9],?21,?-343485551);

????a?
=?safe_add(a,?olda);
????b?
=?safe_add(b,?oldb);
????c?
=?safe_add(c,?oldc);
????d?
=?safe_add(d,?oldd);
??}

??
return?Array(a,?b,?c,?d);

}


/*
?*?These?functions?implement?the?four?basic?operations?the?algorithm?uses.
?
*/

function?md5_cmn(q,?a,?b,?x,?s,?t)
{
??
return?safe_add(bit_rol(safe_add(safe_add(a,?q),?safe_add(x,?t)),?s),b);
}

function?md5_ff(a,?b,?c,?d,?x,?s,?t)
{
??
return?md5_cmn((b?&?c)?|?((~b)?&?d),?a,?b,?x,?s,?t);
}

function?md5_gg(a,?b,?c,?d,?x,?s,?t)
{
??
return?md5_cmn((b?&?d)?|?(c?&?(~d)),?a,?b,?x,?s,?t);
}

function?md5_hh(a,?b,?c,?d,?x,?s,?t)
{
??
return?md5_cmn(b?^?c?^?d,?a,?b,?x,?s,?t);
}

function?md5_ii(a,?b,?c,?d,?x,?s,?t)
{
??
return?md5_cmn(c?^?(b?|?(~d)),?a,?b,?x,?s,?t);
}


/*
?*?Calculate?the?HMAC-MD5,?of?a?key?and?some?data
?
*/

function?core_hmac_md5(key,?data)
{
??
var?bkey?=?str2binl(key);
??
if(bkey.length?>?16)?bkey?=?core_md5(bkey,?key.length?*?chrsz);

??
var?ipad?=?Array(16),?opad?=?Array(16);
??
for(var?i?=?0;?i?<?16;?i++)
??
{
????ipad[i]?
=?bkey[i]?^?0x36363636;
????opad[i]?
=?bkey[i]?^?0x5C5C5C5C;
??}


??
var?hash?=?core_md5(ipad.concat(str2binl(data)),?512?+?data.length?*?chrsz);
??
return?core_md5(opad.concat(hash),?512?+?128);
}


/*
?*?Add?integers,?wrapping?at?2^32.?This?uses?16-bit?operations?internally
?*?to?work?around?bugs?in?some?JS?interpreters.
?
*/

function?safe_add(x,?y)
{
??
var?lsw?=?(x?&?0xFFFF)?+?(y?&?0xFFFF);
??
var?msw?=?(x?>>?16)?+?(y?>>?16)?+?(lsw?>>?16);
??
return?(msw?<<?16)?|?(lsw?&?0xFFFF);
}


/*
?*?Bitwise?rotate?a?32-bit?number?to?the?left.
?
*/

function?bit_rol(num,?cnt)
{
??
return?(num?<<?cnt)?|?(num?>>>?(32?-?cnt));
}


/*
?*?Convert?a?string?to?an?array?of?little-endian?words
?*?If?chrsz?is?ASCII,?characters?>255?have?their?hi-byte?silently?ignored.
?
*/

function?str2binl(str)
{
??
var?bin?=?Array();
??
var?mask?=?(1?<<?chrsz)?-?1;
??
for(var?i?=?0;?i?<?str.length?*?chrsz;?i?+=?chrsz)
????bin[i
>>5]?|=?(str.charCodeAt(i?/?chrsz)?&?mask)?<<?(i%32);
??
return?bin;
}


/*
?*?Convert?an?array?of?little-endian?words?to?a?string
?
*/

function?binl2str(bin)
{
??
var?str?=?"";
??
var?mask?=?(1?<<?chrsz)?-?1;
??
for(var?i?=?0;?i?<?bin.length?*?32;?i?+=?chrsz)
????str?
+=?String.fromCharCode((bin[i>>5]?>>>?(i?%?32))?&?mask);
??
return?str;
}


/*
?*?Convert?an?array?of?little-endian?words?to?a?hex?string.
?
*/

function?binl2hex(binarray)
{
??
var?hex_tab?=?hexcase???"0123456789ABCDEF"?:?"0123456789abcdef";
??
var?str?=?"";
??
for(var?i?=?0;?i?<?binarray.length?*?4;?i++)
??
{
????str?
+=?hex_tab.charAt((binarray[i>>2]?>>?((i%4)*8+4))?&?0xF)?+
???????????hex_tab.charAt((binarray[i
>>2]?>>?((i%4)*8??))?&?0xF);
??}

??
return?str;
}


String.prototype.trim?
=?function(){return?this.replace(/(^s*)|(s*$)/g,?"");}

function?md5(text)?{
????
return?hex_md5(text.trim());
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247892.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247892.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247892.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

函數-函數進階-裝飾器流程分析

老王&#xff1a;算了&#xff0c;估計你也想不出來。。。學過嵌套函數沒有&#xff1f; 你&#xff1a;yes&#xff0c;然后呢&#xff1f; 老王&#xff1a;想實現一開始你寫的america login(america)不觸發你函數的執行&#xff0c;只需要在這個login里面再定義一層函數&am…

制作手寫簽名

<!DOCTYPE html> <!-- saved from url(0056)http://hao2013.cn/canvas-special-master/brush/index.html --> <html><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><title>簽名板(支持移動…

python第五次作業——陳靈院

習題1&#xff1a;讀入文件pmi_days.csv&#xff0c;完成以下操作&#xff1a;1.統計質量等級對應的天數&#xff0c;例如&#xff1a;優&#xff1a;5天良&#xff1a;3天中度污染&#xff1a;2天2.找出PMI2.5的最大值和最小值&#xff0c;分別指出是哪一天。 import csv impo…

iOS 二叉樹相關算法實現

什么是二叉樹&#xff1f; 在計算機科學中&#xff0c;二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”和“右子樹”&#xff0c;左子樹和右子樹同時也是二叉樹。二叉樹的子樹有左右之分&#xff0c;并且次序不能任意顛倒。二叉樹是遞歸定義的&#xff0c;所…

vux 組件庫首次使用安裝

1、首先通過腳手架新建一個項目&#xff0c;過程略。 創建完項目后&#xff0c;在項目里安裝vux&#xff0c; 通過命令 npm install vux --save 安裝 2、安裝vux-loader&#xff0c; 通過命令 npm install vux-loader --save-dev 安裝&#xff08;vux文檔沒說明&#xff09; 3、…

@Component 和 @Bean 的區別

Spring幫助我們管理Bean分為兩個部分&#xff0c;一個是注冊Bean&#xff0c;一個裝配Bean。完成這兩個動作有三種方式&#xff0c;一種是使用自動配置的方式、一種是使用JavaConfig的方式&#xff0c;一種就是使用XML配置的方式。 Compent 作用就相當于 XML配置 Component pub…

js動態驗證碼獲取

<!DOCTYPE html> <html lang"cn"> <head><meta charset"UTF-8"><title>短信驗證碼</title> </head> <body> <input type"number" id"tel" value"13303861063"> <…

Base64 算法原理,以及編碼、解碼【加密、解密】 介紹

Base64編碼&#xff0c;是我們程序開發中經常使用到的編碼方法。它是一種基于用64個可打印字符來表示二進制數據的表示方法。它通常用作存儲、傳輸一些二進制數據編碼方法&#xff01;也是MIME&#xff08;多用途互聯網郵件擴展&#xff0c;主要用作電子郵件標準&#xff09;中…

js通過身份證獲取年齡

// 獲取用戶的身份證號碼let identityCard this.idNum.replace(/\s/g, "");//判斷長度let len identityCard.length;//設置新的變量var strBirthday "";//根據長度獲取年月日if (len 18) {strBirthday identityCard.substr(6, 4) "/" identi…

爬取豆瓣top250

#xpath #第一種方法 可在開發者工具中找到標簽&#xff0c;右鍵copy xpath&#xff0c;有時需去掉tbody標簽 #第二種方法 簡單學習xpath&#xff0c;自己書寫&#xff0c;掌握基本語法即可&#xff0c;簡單的層級關系#先將csv文件以記事本打開&#xff0c;更改編碼為ASNI&…

TCP/IP,Http,Socket,XMPP的區別

網絡由下往上分為 物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。 通過初步的了解&#xff0c;我知道IP協議對應于網絡層&#xff0c;TCP協議對應于傳輸層&#xff0c;而HTTP協議對應于應用層&#xff0c; 三者從本質上來說沒有可比性&#xff0c; socket則是對…

LED音樂頻譜之點陣

轉載請注明出處&#xff1a;http://blog.csdn.net/ruoyunliufeng/article/details/37967455 一.硬件 這里的LED選擇直插的霧面LED&#xff0c;亮度可以還不失美觀。注意每行要加上限流電阻。74HC138&#xff08;三八譯碼器&#xff09;作為列選&#xff0c;每行都連著74HC595&a…

上架相關——App Store 上架流程

說實話&#xff0c;公司要上架一個自己做的一個小項目。為了完成這個任務&#xff0c;菜鳥的我一遍找資料一遍跟著做&#xff0c;一遍修改錯誤一遍查找解決方案。網上的資料大部分都是2015年以前的資料&#xff0c;資料有點不夠過時&#xff0c;而且步驟配圖也不是很詳細&#…

this.$router 的三種跳轉頁面方法

第一種&#xff1a; this.$router.push(需要跳轉到的路徑名稱)此方法跳轉后&#xff0c;會在歷史欄目中保存路勁地址&#xff0c;當點擊歷史標簽時可以進行訪問 第二種&#xff1a; this.$router.replace(需要跳轉到的路徑名稱)此方法跳轉后&#xff0c;會在歷史欄目中不保存…

cf777c

題意&#xff1a;給你一個n*m的數陣 對于一行到另一行&#xff0c;若存在一列從上到下遞減&#xff0c;則稱之符合題意 The first line of the input contains two positive integers n and m (1?≤?nm?≤?100?000) — the number of rows and the number of columns in t…

上架相關——appstore 更新app版本

注&#xff1a;此片文章是基于app已經上架&#xff0c;也就是證書都已經配置好的前提下。 首先是還是app打包 修改版本號 修改project處的pp文件 檢查無誤后打包打包完成后upload to app store 漫長的等待。。 上傳到appstore進入iTunesConnect 選擇我的app 選擇對應app點…

輸入框輸入數字,且不能有小數點存在

基于Vue項目進行設置 <template><comp v-if"update"></comp><button click"reload()">刷新comp組件</button></template><script>import comp from /views/comp.vueexport default {name: parentComp,data() {r…

iOS開發 藍牙技術4.0詳解

前言 前端時間,同學在做項目過程中遇到關于藍牙方面的問題,今天我就給大家進行詳細的進行講解下藍牙在iOS開發中的具體實現.在介紹藍牙前,大家要搞清楚什么是藍牙? 什么是藍牙? 隨著藍牙低功耗技術BLE&#xff08;Bluetooth Low Energy&#xff09;的發展&#xff0c;藍牙技術…

前端面試題(五)

position的屬性有哪些&#xff1f; 1、absolute生成絕對定位的元素&#xff0c;相對于值不為 static的第一個父元素進行定位。 2、fixed &#xff08;老IE不支持&#xff09;生成絕對定位的元素&#xff0c;相對于瀏覽器窗口進行定位。 3、relative生成相對定位的元素&#xff…

qrcode.js 二維碼生成器

二維碼生成 并顯示&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml" xml:lang"ko" …