1.2 密碼學(xué)及安全技術(shù)
1.2.1 密碼學(xué)知識
1.2.1.1 Hash函數(shù)
-
Hash(哈希)
哈希函數(shù)是一類數(shù)學(xué)函數(shù),可以在有限合理的時(shí)間內(nèi),將任意長度的消息壓縮為
固定長度的輸出值,并且是不可逆的。其輸出值稱為哈希值昌屉,也稱為散列值。
hash算法 哈希算法的應(yīng)用:
消息認(rèn)證:確保收到的消息和發(fā)送的消息都是未被篡改的茵瀑。
數(shù)字簽名:對消息摘要進(jìn)行數(shù)字簽名與對消息本身進(jìn)行數(shù)字簽名等效间驮。
口令的安全性:僅將口令的哈希值進(jìn)行保存,進(jìn)行口令檢驗(yàn)時(shí)僅需對比哈希值即可马昨,即使攻擊者獲取了口令的哈希值竞帽,也無法計(jì)算出口令。
數(shù)據(jù)完整性:具有抗數(shù)據(jù)篡改的能力鸿捧。-
Hash函數(shù)在區(qū)塊鏈中的應(yīng)用
在區(qū)塊鏈系統(tǒng)中屹篓,哈希算法得到了廣泛的使用。
在區(qū)塊鏈系統(tǒng)中匙奴,區(qū)塊之間的鏈接就是通過區(qū)塊的哈希值串聯(lián)起來的堆巧。除此以外,還有梅克爾樹的生成計(jì)算泼菌,交易事務(wù)的哈希值計(jì)算等谍肤。
區(qū)塊鏈?zhǔn)且粋€(gè)使用哈希指針構(gòu)建的鏈表
區(qū)塊鏈 -
Merkle tree
Merkle(默克爾)樹,又叫哈希樹哗伯,是一種典型的二叉樹結(jié)構(gòu)荒揣,由一個(gè)根節(jié)點(diǎn)、一組中間節(jié)點(diǎn)和一組葉節(jié)點(diǎn)組成
應(yīng)用場景:
快速比較大量數(shù)據(jù)
快速定位修改
Merkle tree
1.2.1.2橢圓曲線加密算法
即:Elliptic Curve Cryptography焊刹,簡稱ECC系任,是基于橢圓曲線數(shù)學(xué)理論實(shí)現(xiàn)的一種非對稱加密算法恳蹲。 相比RSA,ECC優(yōu)勢是可以使用更短的密鑰俩滥,來實(shí)現(xiàn)與RSA相當(dāng)或更高的安全嘉蕾。據(jù)研究,160位ECC加密安全性相當(dāng)于1024位RSA加密霜旧,210位ECC加密安全性相當(dāng)于2048位RSA加密荆针。
1.2.2 安全技術(shù)
1.2.2.1 數(shù)字簽名
用于防止消息篡改和抵賴的場景
數(shù)字簽名基于非對稱加密,既可以用于證實(shí)內(nèi)容的完整性颁糟,又同時(shí)可以確 認(rèn)來源(或不可抵賴航背,Non-Repudiation)。
數(shù)字簽名的全過程分兩大部分棱貌,即簽名與驗(yàn)證玖媚。一側(cè)為簽名,一側(cè)為驗(yàn)證 過程婚脱。
1.2.2.2 數(shù)字證書
1.2.2.3 PKI體系
1.2.2.4 同態(tài)加密
本質(zhì)上今魔,同態(tài)加密是指這樣一種加密函數(shù),對明文進(jìn)行環(huán)上的加法和乘法運(yùn)算再加密障贸,與加密后對密文進(jìn)行相應(yīng)的運(yùn)算错森,結(jié)果是等價(jià)的。由于這個(gè)良好的性質(zhì)篮洁,人們可以委托第三方對數(shù)據(jù)進(jìn)行處理而不泄露信息涩维。具有同態(tài)性質(zhì)的加密函數(shù)是指兩個(gè)明文a、b滿足Dec(En(a)⊙En(b))=a⊕b的加密函數(shù)袁波,其中En是加密運(yùn)算瓦阐,Dec是解密運(yùn)算,⊙篷牌、⊕分別對應(yīng)明文和密文域上的運(yùn)算睡蟋。當(dāng)⊕代表加法時(shí),稱該加密為加同態(tài)加密:當(dāng)⊕代表乘法時(shí)枷颊,稱該加密為乘同態(tài)加密戳杀。
全同態(tài)加密是指同時(shí)滿足加同態(tài)和乘同態(tài)性質(zhì),可以進(jìn)行任意多次加和乘運(yùn)算的加密函數(shù)夭苗。用數(shù)學(xué)公式來表達(dá)信卡,即Dec(f(En(m1),En(m2)听诸,…坐求,En(mk)))=f(m1蚕泽,m2晌梨,…桥嗤,mk),或?qū)懗桑篺(En(m1)仔蝌,En(m2)泛领,…,En(mk))=En(f(m1敛惊,m2渊鞋,…,mk))瞧挤,如果f是任意函數(shù)锡宋,稱為全同態(tài)加密。
1.2.2.5 布隆過濾器
class BloomHash {
/**
* Hash工具類返回的hashcode的最大長度<br>
* maxLength為2的n次方特恬,返回的hashcode為[0,2^n-1]
*/
public int maxLength;
// Hash函數(shù)生成哈希碼的關(guān)鍵字
public int seed;
public BloomHash(int maxLength, int seed) {
this.maxLength = maxLength;
this.seed = seed;
}
/**
* 返回字符串string的hashcode执俩,大小為[0,maxLength-1]
*
* @param string
* @return
*/
public int hashCode(String string) {
int result = 0;
// 這個(gè)構(gòu)建hashcode的方式類似于java的string的hashcode方法
// 只是我這里是可以設(shè)置的seed,它那里是31
for (int i = 0; i < string.length(); i++) {
char a = string.charAt(i);
int b = seed * a; // 隱式的把字符轉(zhuǎn)換為整數(shù)(ASSIC碼)
result = result + b;
}
/**
* public static int indexFor(int m, int n){ return m & (n - 1); } public static
* void main(String[] args) { System.out.println("19 與 16 求余 = "+ indexFor(19,
* 16) ); System.out.println("19 與 16 求余 = "+ 19 % 16 ); }
* 此方法中n為2的指數(shù)值癌刽,則其二進(jìn)制形式的表示中只存在一個(gè)1役首,其余位都為0, 例如: 0000 1000显拜、0100 0000衡奥、0010
* 0000等等。則n-1的二進(jìn)制形式就為1的位數(shù)變?yōu)?远荠, 其右邊位全變?yōu)?矮固,例如16的二進(jìn)制 0001 0000 -1 = 0000
* 1111測試m為19的二進(jìn)制 0001 0011 & 0000 1111 = 0000 0011 = 3,地位保留的結(jié)果便是余數(shù)譬淳。此位運(yùn)算也是
* HashMap中確定元素鍵(key)值所在哈希數(shù)組下標(biāo)位置的核心方法乏屯,此位運(yùn)算(hash & (length - 1)) 的效率極高于hash %
* length的求余, 所以也解釋為什么HashMap的擴(kuò)容始終為2的倍數(shù)(2的指數(shù)值)。
*/
// 保證結(jié)果在[0,maxLength-1]:equal to 'result % maxLength'
return result & (maxLength - 1);
}
}
public class BloomFilter {
// 構(gòu)建hash函數(shù)的關(guān)鍵字瘦赫,總共7個(gè)
private static final int[] HashSeeds = new int[] { 3, 5, 7, 11, 13, 17, 19 };
// Hash工具類的數(shù)組
private static BloomHash[] HashList = new BloomHash[HashSeeds.length];
// BloomFilter的長度辰晕,最好為插入數(shù)量的10倍,目前為2的20次方确虱,大約100萬個(gè)
private static final int BloomLength = 1 << 20;
// 對位的操作類含友,java自帶的BitSet,共BloomLength個(gè)bit
private BitSet bitSet = new BitSet(BloomLength);
public BloomFilter() {
// 初始化Hash工具類的數(shù)組,每個(gè)hash工具類的hash函數(shù)都不同
for (int i = 0; i < HashSeeds.length; i++) {
HashList[i] = new BloomHash(BloomLength, HashSeeds[i]);
}
}
/**
* 在布隆過濾器中加入值value校辩,在多個(gè)hash函數(shù)生成的hashcode對應(yīng)的位置上窘问,置1
*
* @param value字符串,如果為數(shù)字宜咒,可以自己轉(zhuǎn)化成string
*/
public void addValue(String value) {
for (int i = 0; i < HashSeeds.length; i++) {
// 根據(jù)對應(yīng)的hash函數(shù)得到hashcode
int hashcode = HashList[i].hashCode(value);
// 在位圖中惠赫,將對應(yīng)的位,設(shè)置為1
bitSet.set(hashcode);
}
}
/**
* 在布隆過濾器中,檢驗(yàn)是否可能有值value
*
* @param value
* @return 如果返回false故黑,則一定沒有<br>
* 如果返回true儿咱,就代表有可能有
*/
public boolean existsValue(String value) {
boolean result = true;
for (int i = 0; i < HashSeeds.length; i++) {
// 根據(jù)對應(yīng)的hash函數(shù)得到hashcode
int hashcode = HashList[i].hashCode(value);
/**
* 隱式把boolean轉(zhuǎn)換為整數(shù)進(jìn)行按位與運(yùn)算 “短路” 主要用于邏輯運(yùn)算符中庭砍,即 “ ! && || "這三種運(yùn)算符 短路 就是知如果左側(cè)的
* 表達(dá)式能確定運(yùn)算后的結(jié)果,則不再計(jì)算右側(cè)的表達(dá)式混埠。 如(1>2)&&(2<3) 明明左側(cè)已經(jīng)為假 了 我 不用計(jì)算右側(cè)我一定知道 此表達(dá)是為假
*/
// 將result與對應(yīng)位置上的0或1 做與運(yùn)算
// 如果全為1怠缸,則result最后為1
// 如果有一個(gè)位置上為0,則最后result為0
result = result & bitSet.get(hashcode);
}
return result;
}
}