标签:碰撞 数据 区别 advance 一起 rar apollo header 文档
参考文档:
SubtleCrypto:https://developer.mozilla.org/zh-CN/docs/Web/API/SubtleCrypto
RSA算法原理:https://cjting.me/2020/03/13/rsa/
DH算法原理:https://blog.csdn.net/mrpre/article/details/52608867
web cryptography API:https://www.theseus.fi/bitstream/handle/10024/92960/Web_Cryptography_API_Luoma-aho.pdf
《深入浅出https》
《java加密与解密艺术》
《Understanding-Cryptography》
替换密码,比如:A→k B→d C→w ...
移位密码,如凯撒加密,右移3位
但这些可以暴力破解,或通过字母出现的概率进行分析破解,比如英文单词里e的出现频率最高。
根据克劳德·香农的信息理论,强加密算法的两个原操作:
翻译过来:
密码学主要解决四个问题:
对称和非对称算法密钥长度不同,80位的对称密钥和1024位的RSA安全性相当。
不管是真正的随机数生成器TRNG(True Random Number Generator),伪随机数生成器PRNG(Preudo Random Number Generator),还是密码学伪随机数生成器CPRNG(Cryptography secure Preudo Random Number Generator),内部工作原理是一样的,CPRNG是PRNG随机数生成器中的一种。
随机数生成器内部会维护一个状态(internal state),对于TRNG来说,内部状态的数值来自外部设备,称为熵(entrory),比如动态的时间、变化的温度、声音的变化、鼠标位置。
而对于PRNG来说,内部状态的数值来自于模拟的数值,称为种子(seed)。随机数生成器每次生成随机数的时候,内部状态的值都会变化,这样才能产生不一样的随机数,如果每次
熵和种子是一样的,生成的随机数也是相同的,所以熵和种子对于随机数生成器非常重要。
一个优秀的随机数生成器就在于寻找尽可能多的熵和种子,一旦熵和种子不够,随机数生成器就会停止运行。
我们不用关心这些,各语言的加解密库一般提供了密码学安全的随机数生成方法
流密码(stream cipher) A5/1,RC4等,多用于手机端,效率高,对资源比较少的设备比较合适。但目前RC4已经证实不安全。
OTP(一次一密),无条件安全(不考虑计算资源的情况下安全)
采用PRNG和CPRNG生成的就实用的多,只需要提供一个种子key,密钥比消息短的多
分组密码(block cipher),或块密码。有很多迭代模式:
将明文拆分成多个数据块,每个数据块的长度等于分组长度,如果最后一个数据块长度小于分组长度,需要进行填充保证最后一个数据块长度等于分组长度。
依次对每个数据块进行迭代得到每个数据块的密文分组,将所有密文分组组合在一起就得到最终的密文,密文长度等同于明文长度。
ECB模式最大的特点就是每个迭代过程都是独立的,是可以并行处理的,能够加快运算速度。由于固定的明文和密钥每次运算的结果都是相同的,这会造成很多安全问题。
引入初始化向量(IV)
初始化向量必须每次都不一样,有了随机的初始化向量,同样的明文和密钥最终得到的密文是不一样的,解决了ECB模式存在的安全问题。
does-iv-work-like-salt?
为什么要在密码里加点“盐”
密文拆分成多个数据块,和CBC迭代不一样的是不需要进行填充处理。
在处理迭代之前,先生成每个密钥流,有n个数据块,就有n个密钥流。根据第n个密钥流可以得到第n+1个密钥流,最简单的方式就是密钥流每次递增加一。
第一个密钥流的获取方式也很简单,就是生成一个随机值(Nonce),Nonce和IV可以等同理解,一个不容易推导出来的随机值。
接下来进行迭代加密处理,密钥流和密钥进行处理,得到的值再和数据块进行XOR运算(每次迭代相当于流密码运行模式)得到密文分组。
迭代运行每个数据块,最终得到密文。
填充标准
明文必须是分组的倍数,如果不是,就需要填充。有一些标准定义了如何进行填充:PKCS#7和PKCS#5里面有定义填充标准
最简单的方式都填充0,但如果明文本身末尾有0,解密出来的就不是原文了
PKCS#7 很简单,根据填充的字节数量进行对应的填充,如果填充的字节长度n是3,填充的值就是030303;如果n是5,那么填充的值就是0505050505,填充值最后一个字节代表的就是实际填充的长度。
PKCS#5和PKCS#7处理填充机制的方式其实是一样的,只是PKCS#5处理的分组长度只能是8字节,而PKCS#7处理的分组长度可以是1到255任意字节,从这个角度看,可以认为PKCS#5是PKCS#7标准的子集。AES算法中分组长度没有8字节,所以AES算法使用PKCS#7标准。
内部实现很复杂,略
DES已被破解
typedef struct rsa_st {
BIGNUM *p;
BIGNUM *q;
BIGNUM *n;
BIGNUM *e;
BIGNUM *d;
} RSA;
[n,e]就是公钥
[n,d]就是私钥
想知道d需要对n进行质数分解,n是个大整数,所以相当困难。
RSA原理(很容易理解):
https://cjting.me/2020/03/13/rsa
Alice 和Bob想要在一个不安全的信道共享一个密钥?
DH算法原理 (也很容易理解)
设 已知 二元组(q, p)
Alice 生成随机值a,计算q^a mod p = Ga
Bob 生成随机值b, 计算q^b mod p = Gb
Alice 计算Sa =Gb^a mod p
Bob 计算Sb = Ga^b mod p
a,b私钥,Ga,Gb是公钥,计算出a和b是相当困难
Sa = Sb ?
群,阿贝尔群,循环群,本原元(生成元)....不展开
其实P就是一个循环群,q是本原元
加了模运算的对数运算是相当难的,比大整数质数分解还要难!NP问题
基于ECC的DH,ECDH
ECC没有直接提供一个加密方法,但我们可以使用ECDH产生一个共有的密钥,然后用对称加密方案进行加密
非对称秘钥方案都基于单向函数f(x),求解其逆函数f(x)^-1的解相当困难
RSA基于大整数分解,DH,ECC和ElGamal都是基于离散对数问题
ps:或许哪天出现了好的数学方法来解决这些问题,那这些加密方案将都不再安全
Ecc原理解析:
https://zhuanlan.zhihu.com/p/103665076
实际应用中,我们通常使用非对称加密方案来加解密对称秘钥,再由对称秘钥对明文进行加解密
加密:
解密:
数字签名技术有以下几个特点。
RSA
DSA
ECDSA:(r,s,v) 略
v = 27 + (y % 2)
密码学Hash算法的主要特性如下:
主要用途:
MD5是不安全的,产生了碰撞(不同的数据,得到相同的hash值)
目前SHA1已经被攻破,SHA2被攻破只是时间问题。
不细讲,只提和hash的区别:
消息认证码(mac)是带密钥的,
hashes 用于保证数据的完整性, MAC 保证完整性和身份验证
构造方法上通常基于Hash函数,比如HMAC,MDx-MAC。也可以基于分组密码比如CBC类的MAC,还有就是基于泛Hash函数族。
TSL内部就有各种密码套件,实现安全传输
数字证书就类似于我们的身份证,用来标识网络中的用户(计算机)身份
可以看下百度的证书链。
Base64算法最早应用于解决电子邮件传输的问题。在早期,由于“历史问题”,电子邮件只允许ASCII码字符。如果要传输一封带有非ASCII码字符的电子邮件,当它通过有“历史问题”的网关时就可能出现问题。这个网关很可能会对这个非ASCII码字符的二进制位做调整,即将这个非ASCII码的8位二进制码的最高位置为0。此时用户收到的邮件就会是一封纯粹的乱码邮件了。基于这个原因产生了Base64算法。
余数 = 原文字节数 mod 3
余数为0 则没有等号
余数为1 则要补2个等号
余数为2 则要补1个等号
JS里的Array,因为有很多功能,而且是不限制类型的,或者它还可能是稀疏的(和java和c++等区别)……总之这个Array是“托管”的,它内部有比较复杂的实现。而如果你从XHR、File API、Canvas等等各种地方,读取了一大串字节流,如果用JS里的Array去存,又浪费,又低效。于是为了配合这些新的API增强JS的二进制处理能力,就有了ArrayBuffer。
ArrayBuffer对象:代表内存之中的一段二进制数据,可以通过“视图”进行操作。“视图”部署了数组接口,这意味着,可以用数组的方法操作内存。
TypedArray对象:用来生成内存的视图,通过9个构造函数,可以生成9种数据格式的视图,比如Uint8Array(无符号8位整数)数组视图, Int16Array(16位整数)数组视图, Float32Array(32位浮点数)数组视图等等。
DataView对象:用来生成内存的视图,可以自定义格式和字节序,比如第一个字节是Uint8(无符号8位整数)、第二个字节是Int16(16位整数)、第三个字节是Float32(32位浮点数)等等。
简单说,ArrayBuffer对象代表原始的二进制数据,TypedArray对象代表确定类型的二进制数据,DataView对象代表不确定类型的二进制数据。它们支持的数据类型一共有9种(DataView对象支持除Uint8C以外的其他8种)
在Node.js 里有一个与ArrayBuffer 相似的类叫做Buffer,但更强大一些。
谁都知道小偷可以翻窗户进来,但出门的时候没人会不锁门
js的加解密有很多弊端,比如:
一些流行的js加解密库:
Stanford JavaScript Crypto Library(sjcl)
CryptoJS
Forge
基于openssl,底层是C封装。
具体API见官网 crypto api
开发者需要熟知浏览器环境的安全常识:
规则让浏览器知道网站只能通过http安全连接来访问
规则通知浏览器应该从何处加载资源
它允许web主机运营商指导用户代理在一段时间内强制使用特定的加密身份,从而有效地减轻某些中间人攻击
它允许用户代理在不进行意外操作的情况下验证获取的资源是否已被传递。
签名验签
const enc = new TextEncoder();
const encodedMessage = enc.encode(‘hello‘);
console.log(encodedMessage)
const keyPair = window.crypto.subtle.generateKey({
name: "RSASSA-PKCS1-v1_5",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
["sign", "verify"]
);
(async () => {
const {
privateKey,
publicKey
} = await keyPair;
const signature = await window.crypto.subtle.sign(
"RSASSA-PKCS1-v1_5",
privateKey,
encodedMessage
);
const signatureValid = await window.crypto.subtle.verify("RSASSA-PKCS1-v1_5", publicKey, signature, encodedMessage);
console.log(signatureValid);
})()
加密解密
const enc = new TextEncoder();
const dec = new TextDecoder();
const keyPair = window.crypto.subtle.generateKey({
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
["encrypt", "decrypt"]
);
const encodedMessage = enc.encode(‘hello‘);
(async () => {
const {
privateKey,
publicKey
} = await keyPair;
const encryptedText = await window.crypto.subtle.encrypt({
name: "RSA-OAEP"
},
publicKey,
encodedMessage
)
console.log(encryptedText);
const decryptedText = await window.crypto.subtle.decrypt({
name: "RSA-OAEP"
},
privateKey,
encryptedText
)
console.log(decryptedText);
console.log(dec.decode(decryptedText));
})()
let array = new Uint32Array(10);
window.crypto.getRandomValues(array);
for (const num of array) {
console.log(num);
}
其他相关链接:
What is the importance of Modular arithmetic in cryptography?
标签:碰撞 数据 区别 advance 一起 rar apollo header 文档
原文地址:https://www.cnblogs.com/johnzhu/p/12831970.html