1
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
## 1.0.3(2025-08-17)
|
||||
* 兼容支持鸿蒙 Next
|
||||
## 1.0.2(2025-03-15)
|
||||
* 更新所有端都支持同样的加密方案。
|
||||
## 1.0.1(2025-02-28)
|
||||
* 补齐hmacSha512,sha512,aesEncrypt,aesDecrypt增加keySize加密位,增加了generateRSAKeyPair生成RSA密钥对.
|
||||
## 1.0.0(2024-12-24)
|
||||
* 常用 加密 三端可用.暂不支持sm2,sm3,sm4,下个版本提供.
|
||||
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"id": "x-crypto-s",
|
||||
"displayName": "x-crypto-s",
|
||||
"version": "1.0.0",
|
||||
"description": "x-crypto-s",
|
||||
"keywords": [
|
||||
"x-crypto-s"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.6.8"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "uts",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "",
|
||||
"data": "",
|
||||
"permissions": ""
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "u",
|
||||
"aliyun": "u",
|
||||
"alipay": "u"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "u",
|
||||
"vue3": "u"
|
||||
},
|
||||
"App": {
|
||||
"app-android": "u",
|
||||
"app-ios": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "u",
|
||||
"Android Browser": "u",
|
||||
"微信浏览器(Android)": "u",
|
||||
"QQ浏览器(Android)": "u"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "u",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "u",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
# x-crypto-s
|
||||
### 开发文档
|
||||
[TMUI4.0文档](https://xui.tmui.design/)
|
||||
[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369)
|
||||
|
||||
加密插件
|
||||
|
||||
### 说明
|
||||
这是tmui4.0|XUI的原生插件附赠插件,提供了多种加密算法的实现,包括MD5、Base64、SHA系列、AES、DES、RSA和RC4等。所有加密算法均采用原生加密代码实现,与CryptoJS加密结果完全一致。
|
||||
|
||||
### 兼容性
|
||||
|
||||
| Harmony | IOS | Android | WEB | 小程序 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 支持 | 支持 | 支持 | 支持 | 支持 |
|
||||
|
||||
### API说明
|
||||
|
||||
#### MD5加密
|
||||
```ts
|
||||
function md5(str: string): string
|
||||
```
|
||||
- 参数:
|
||||
- str: 待加密的字符串
|
||||
- 返回值:MD5加密后的字符串
|
||||
|
||||
#### Base64编解码
|
||||
```ts
|
||||
function base64Encode(str: string): string
|
||||
function base64Decode(str: string): string
|
||||
```
|
||||
- 参数:
|
||||
- str: 待编码/解码的字符串
|
||||
- 返回值:Base64编码/解码后的字符串
|
||||
- 注意:在Web端加密中文字符时,需要先使用encodeURI处理
|
||||
|
||||
#### SHA系列加密
|
||||
```ts
|
||||
function sha256(str: string): string
|
||||
function sha512(str: string): string
|
||||
function sha1(str: string): string
|
||||
function hmacSha256(key: string, data: string): string
|
||||
function hmacSha512(key: string, data: string): string
|
||||
```
|
||||
- 参数:
|
||||
- str/data: 待加密的字符串
|
||||
- key: HMAC加密的密钥
|
||||
- 返回值:对应算法加密后的字符串
|
||||
|
||||
#### AES加密
|
||||
```ts
|
||||
function aesEncrypt(key: string, data: string, mode: string = "ECB", iv: string|null = null, keySize: number|null = null): string
|
||||
function aesDecrypt(key: string, data: string, mode: string = "ECB", iv: string|null = null, keySize: number|null = null): string
|
||||
```
|
||||
- 参数:
|
||||
- key: 加密密钥(UTF-8字符串,根据keySize截取和补足)
|
||||
- data: 待加密/解密的数据
|
||||
- mode: 加密模式,支持ECB和CBC
|
||||
- iv: 初始化向量
|
||||
- keySize: 密钥长度(16=128位, 24=192位, 32=256位)
|
||||
- 返回值:加密/解密后的字符串
|
||||
|
||||
#### DES加密
|
||||
```ts
|
||||
function desEncrypt(key: string, data: string, mode: string = "ECB", iv: string|null = null): string
|
||||
function desDecrypt(key: string, data: string, mode: string = "ECB", iv: string|null = null): string
|
||||
```
|
||||
- 参数:
|
||||
- key: 加密密钥
|
||||
- data: 待加密/解密的数据
|
||||
- mode: 加密模式,支持ECB和CBC
|
||||
- iv: 初始化向量
|
||||
- 返回值:加密/解密后的字符串
|
||||
|
||||
#### RSA加密
|
||||
```ts
|
||||
function generateRSAKeyPair(keySize: number = 2048): RSARANDOMKEY
|
||||
function rsaEncrypt(publicKey: string, data: string): string
|
||||
function rsaDecrypt(privateKey: string, data: string): string
|
||||
```
|
||||
- 参数:
|
||||
- keySize: RSA密钥长度
|
||||
- publicKey: 公钥
|
||||
- privateKey: 私钥
|
||||
- data: 待加密/解密的数据
|
||||
- 返回值:
|
||||
- generateRSAKeyPair: 返回包含publicKey和privateKey的对象
|
||||
- rsaEncrypt/rsaDecrypt: 加密/解密后的字符串
|
||||
|
||||
#### RC4加密
|
||||
```ts
|
||||
function rc4Encrypt(key: string, data: string): string
|
||||
function rc4Decrypt(key: string, data: string): string
|
||||
```
|
||||
- 参数:
|
||||
- key: 加密密钥
|
||||
- data: 待加密/解密的数据
|
||||
- 返回值:加密/解密后的字符串(hex格式)
|
||||
|
||||
### 使用示例
|
||||
|
||||
```ts
|
||||
import {
|
||||
md5, sha256, sha512, sha1, hmacSha256, hmacSha512,
|
||||
base64Encode, base64Decode,
|
||||
aesEncrypt, aesDecrypt,
|
||||
desEncrypt, desDecrypt,
|
||||
rsaEncrypt, rsaDecrypt,
|
||||
rc4Encrypt, rc4Decrypt,
|
||||
generateRSAKeyPair
|
||||
} from '@/uni_modules/x-crypto-s'
|
||||
|
||||
// MD5加密
|
||||
const md5Result = md5("TMUI4.0X")
|
||||
|
||||
// Base64编解码
|
||||
const base64Result = base64Encode("TMUI4.0X")
|
||||
const decodedText = base64Decode(base64Result)
|
||||
|
||||
// SHA系列加密
|
||||
const sha256Result = sha256("TMUI4.0X")
|
||||
const hmacResult = hmacSha256("密钥", "TMUI4.0X")
|
||||
|
||||
// AES加密(CBC模式)
|
||||
const aesResult = aesEncrypt(
|
||||
"1234567890abcdef",
|
||||
"TMUI4.0X",
|
||||
"CBC",
|
||||
"1234567890abcdef"
|
||||
)
|
||||
const aesDecrypted = aesDecrypt(
|
||||
"1234567890abcdef",
|
||||
aesResult,
|
||||
"CBC",
|
||||
"1234567890abcdef"
|
||||
)
|
||||
|
||||
// RSA加密
|
||||
const rsaKeys = generateRSAKeyPair()
|
||||
const encrypted = rsaEncrypt(rsaKeys.publicKey, "TMUI4.0X")
|
||||
const decrypted = rsaDecrypt(rsaKeys.privateKey, encrypted)
|
||||
```
|
||||
|
||||
更多使用示例和在线加密对比工具:
|
||||
- MD5/SHA对比:https://www.mklab.cn/utils/md5
|
||||
- DES对比:https://www.mklab.cn/utils/des
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"minSdkVersion": "21"
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
package uts.sdk.modules.utsXcryptoS
|
||||
|
||||
import java.security.*
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import javax.crypto.*
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import android.util.Base64
|
||||
import java.nio.charset.Charset
|
||||
import io.dcloud.uts.console
|
||||
import java.security.KeyPair
|
||||
import java.security.KeyPairGenerator
|
||||
import java.security.spec.RSAKeyGenParameterSpec
|
||||
|
||||
|
||||
import java.security.KeyFactory
|
||||
|
||||
|
||||
|
||||
|
||||
// 定义支持的输出长度枚举
|
||||
enum class OutputLength(val length: Int) {
|
||||
LENGTH_16(8), // 8 bytes = 16 hex chars
|
||||
LENGTH_32(16), // 16 bytes = 32 hex chars
|
||||
LENGTH_64(32) // 32 bytes = 64 hex chars
|
||||
}
|
||||
data class RSARandomKey(val publicKey: String, val privateKey: String)
|
||||
|
||||
|
||||
class UniversalCryptoHelper {
|
||||
companion object {
|
||||
// MD5 Encryption ,32位加密
|
||||
fun md5(input: String): String {
|
||||
val md = MessageDigest.getInstance("MD5")
|
||||
val digest = md.digest(input.toByteArray())
|
||||
return digest.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
|
||||
// BASE64 Encoding and Decoding
|
||||
fun base64Encode(input: String): String = Base64.encodeToString(input.toByteArray(), android.util.Base64.NO_WRAP)
|
||||
fun base64Decode(input: String): String = String(Base64.decode(input, Base64.DEFAULT))
|
||||
|
||||
// HMAC with SHA-256
|
||||
fun hmacSha256(key: String, data: String): String {
|
||||
val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA256")
|
||||
val mac = Mac.getInstance("HmacSHA256")
|
||||
mac.init(secretKey)
|
||||
val hash = mac.doFinal(data.toByteArray())
|
||||
return hash.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
|
||||
// SHA-1 and SHA-256 Hashing
|
||||
fun sha1(input: String): String {
|
||||
val md = MessageDigest.getInstance("SHA-1")
|
||||
val digest = md.digest(input.toByteArray())
|
||||
return digest.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
|
||||
fun sha256(input: String): String {
|
||||
val md = MessageDigest.getInstance("SHA-256")
|
||||
val digest = md.digest(input.toByteArray())
|
||||
return digest.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算SHA-512哈希值
|
||||
* @param input 需要计算哈希的字符串
|
||||
* @return 哈希值的十六进制字符串
|
||||
*/
|
||||
fun sha512(input: String): String {
|
||||
val md = MessageDigest.getInstance("SHA-512")
|
||||
val digest = md.digest(input.toByteArray())
|
||||
return digest.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用HMAC-SHA512算法计算消息认证码
|
||||
* @param key 密钥
|
||||
* @param data 需要认证的数据
|
||||
* @return HMAC值的十六进制字符串
|
||||
*/
|
||||
fun hmacSha512(key: String, data: String): String {
|
||||
val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA512")
|
||||
val mac = Mac.getInstance("HmacSHA512")
|
||||
mac.init(secretKey)
|
||||
val hmacBytes = mac.doFinal(data.toByteArray())
|
||||
return hmacBytes.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
|
||||
fun generateAesKey(key: String, keySize: Int = 16): ByteArray {
|
||||
val fixedKey = key.padEnd(keySize, '0') // 填充到 16 字节(128 位)
|
||||
return fixedKey.toByteArray().copyOf(keySize) // 截断或扩展为 16 字节
|
||||
}
|
||||
|
||||
fun generateDesKey(key: String,keySize: Int = 24): ByteArray {
|
||||
// 确保密钥长度为24字节,不足时用0填充,过长时截断
|
||||
val keyBytes = key.toByteArray()
|
||||
val paddedKey = ByteArray(keySize)
|
||||
if (keyBytes.size < keySize) {
|
||||
System.arraycopy(keyBytes, 0, paddedKey, 0, keyBytes.size)
|
||||
} else {
|
||||
System.arraycopy(keyBytes, 0, paddedKey, 0, keySize)
|
||||
}
|
||||
return paddedKey
|
||||
}
|
||||
fun generateDesKey2(key: ByteArray,keySize: Int = 24): ByteArray {
|
||||
// 确保密钥长度为24字节,不足时用0填充,过长时截断
|
||||
val keyBytes = key
|
||||
val paddedKey = ByteArray(keySize)
|
||||
if (keyBytes.size < keySize) {
|
||||
System.arraycopy(keyBytes, 0, paddedKey, 0, keyBytes.size)
|
||||
} else {
|
||||
System.arraycopy(keyBytes, 0, paddedKey, 0, keySize)
|
||||
}
|
||||
return paddedKey
|
||||
}
|
||||
/**
|
||||
* 返回编码为base64,cbc或者ecb,填充这pkcs5/pkdcs7,密钥和iv偏移均为16位
|
||||
*/
|
||||
fun aesEncrypt(input: String, key: String,mode:String,iv: String? = null,keySize:Int?=16): String {
|
||||
|
||||
if(mode=="ECB"){
|
||||
val secretKey = SecretKeySpec(generateDesKey(key,keySize?:16), "AES")
|
||||
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
|
||||
val encrypted = cipher.doFinal(input.toByteArray())
|
||||
return Base64.encodeToString(encrypted, Base64.NO_WRAP)
|
||||
}
|
||||
// cbc
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
val keySpec = SecretKeySpec(generateDesKey(key,keySize?:16), "AES")
|
||||
|
||||
val ivSpecBz = generateDesKey(iv?:"",16)
|
||||
val ivSpec = IvParameterSpec(ivSpecBz)
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
|
||||
val encrypted = cipher.doFinal(input.toByteArray())
|
||||
return Base64.encodeToString(encrypted, Base64.NO_WRAP)
|
||||
}
|
||||
fun aesEncrypt2(input: ByteArray, key: ByteArray,mode:String,iv: ByteArray? = null,keySize:Int?=16): ByteArray {
|
||||
|
||||
if(mode=="ECB"){
|
||||
val secretKey = SecretKeySpec(generateDesKey2(key,keySize?:16), "AES")
|
||||
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
|
||||
val encrypted = cipher.doFinal(input)
|
||||
return encrypted
|
||||
}
|
||||
// cbc
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
val keySpec = SecretKeySpec(generateDesKey2(key,keySize?:16), "AES")
|
||||
|
||||
val ivSpecBz = generateDesKey2(iv?:ByteArray(keySize?:16),16)
|
||||
val ivSpec = IvParameterSpec(ivSpecBz)
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
|
||||
val encrypted = cipher.doFinal(input)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
/**
|
||||
* 加密文本为base64,cbc或者ecb,填充这pkcs5/pkdcs7,密钥和iv偏移均为16位,返回字符串.
|
||||
*/
|
||||
fun aesDecrypt(input: String, key: String,mode:String,iv: String? = null,keySize:Int?=16): String {
|
||||
if(mode=="ECB"){
|
||||
val secretKey = SecretKeySpec(generateDesKey(key,keySize?:16), "AES")
|
||||
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey)
|
||||
val decrypted = cipher.doFinal(Base64.decode(input, Base64.DEFAULT))
|
||||
return String(decrypted)
|
||||
}
|
||||
// cbc
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
val keySpec = SecretKeySpec(generateDesKey(key,keySize?:16), "AES")
|
||||
// val ivSpec = adjustIV(iv?:"":iv,keySize?:16)
|
||||
// val ivSpec = IvParameterSpec(iv!!.toByteArray())
|
||||
val ivSpecBz = generateDesKey(iv?:"",16)
|
||||
val ivSpec = IvParameterSpec(ivSpecBz)
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec)
|
||||
val decodedBytes = Base64.decode(input, Base64.DEFAULT)
|
||||
val decrypted = cipher.doFinal(decodedBytes)
|
||||
return String(decrypted)
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun aesDecrypt2(input: ByteArray, key: ByteArray,mode:String,iv: ByteArray? = null,keySize:Int?=16): ByteArray {
|
||||
if(mode=="ECB"){
|
||||
val secretKey = SecretKeySpec(generateDesKey2(key,keySize?:16), "AES")
|
||||
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey)
|
||||
val decrypted = cipher.doFinal(input)
|
||||
// val decrypted = cipher.doFinal(Base64.decode(input, Base64.DEFAULT))
|
||||
return decrypted
|
||||
}
|
||||
// cbc
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
val keySpec = SecretKeySpec(generateDesKey2(key,keySize?:16), "AES")
|
||||
// val ivSpec = adjustIV(iv?:"":iv,keySize?:16)
|
||||
// val ivSpec = IvParameterSpec(iv!!.toByteArray())
|
||||
val ivSpecBz = generateDesKey2(iv?:ByteArray(keySize?:16),16)
|
||||
val ivSpec = IvParameterSpec(ivSpecBz)
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec)
|
||||
// val decodedBytes = Base64.decode(input, Base64.DEFAULT)
|
||||
val decrypted = cipher.doFinal(input)
|
||||
return decrypted
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// DES Encryption and Decryption
|
||||
fun desEncrypt(input: String, key: String,mode:String,iv: String? = null): String {
|
||||
val secretKey = SecretKeySpec(generateDesKey(key), "DESede")
|
||||
val cipher: Cipher = when (mode) {
|
||||
"ECB" -> Cipher.getInstance("DESede/ECB/PKCS5Padding")
|
||||
"CBC" -> Cipher.getInstance("DESede/CBC/PKCS5Padding")
|
||||
else -> throw IllegalArgumentException("Unsupported mode: $mode")
|
||||
}
|
||||
|
||||
if (mode == "CBC" && iv == null) {
|
||||
throw IllegalArgumentException("IV must not be null for CBC mode")
|
||||
}
|
||||
|
||||
if (mode == "CBC") {
|
||||
val ivSpec = IvParameterSpec(iv!!.toByteArray())
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec)
|
||||
} else {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
|
||||
}
|
||||
|
||||
val encrypted = cipher.doFinal(input.toByteArray())
|
||||
return Base64.encodeToString(encrypted, android.util.Base64.NO_WRAP)
|
||||
}
|
||||
|
||||
fun desDecrypt(input: String, key: String,mode:String,iv: String? = null): String {
|
||||
val secretKey = SecretKeySpec(generateDesKey(key), "DESede")
|
||||
val cipher: Cipher = when (mode) {
|
||||
"ECB" -> Cipher.getInstance("DESede/ECB/PKCS5Padding")
|
||||
"CBC" -> Cipher.getInstance("DESede/CBC/PKCS5Padding")
|
||||
else -> throw IllegalArgumentException("Unsupported mode: $mode")
|
||||
}
|
||||
|
||||
if (mode == "CBC" && iv == null) {
|
||||
throw IllegalArgumentException("IV must not be null for CBC mode")
|
||||
}
|
||||
|
||||
if (mode == "CBC") {
|
||||
val ivSpec = IvParameterSpec(iv!!.toByteArray())
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec)
|
||||
} else {
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey)
|
||||
}
|
||||
|
||||
val decrypted = cipher.doFinal(Base64.decode(input, Base64.DEFAULT))
|
||||
return String(decrypted)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Convert String to PublicKey
|
||||
fun stringToPublicKey(publicKeyStr: String): PublicKey {
|
||||
|
||||
val keyBytes = Base64
|
||||
.decode(publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||
.replace("-----END PUBLIC KEY-----", "")
|
||||
.replace("\r", "")
|
||||
.replace("\n", "")
|
||||
.replace("\t", "")
|
||||
.replace(" ", "")
|
||||
, Base64.DEFAULT
|
||||
)
|
||||
|
||||
val keySpec = X509EncodedKeySpec(keyBytes)
|
||||
val keyFactory = KeyFactory.getInstance("RSA")
|
||||
return keyFactory.generatePublic(keySpec)
|
||||
}
|
||||
|
||||
// Convert String to PrivateKey
|
||||
fun stringToPrivateKey(privateKeyStr: String): PrivateKey {
|
||||
val keyBytes = Base64.decode(privateKeyStr.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||
.replace("-----END PRIVATE KEY-----", "")
|
||||
.replace("\r", "")
|
||||
.replace("\n", "")
|
||||
.replace("\t", "")
|
||||
.replace(" ", "")
|
||||
, Base64.DEFAULT
|
||||
)
|
||||
val keySpec = PKCS8EncodedKeySpec(keyBytes)
|
||||
val keyFactory = KeyFactory.getInstance("RSA")
|
||||
return keyFactory.generatePrivate(keySpec)
|
||||
}
|
||||
|
||||
|
||||
fun generateRSAKeyPair(keySize: Int = 2048): RSARandomKey {
|
||||
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
||||
keyPairGenerator.initialize(RSAKeyGenParameterSpec(keySize, RSAKeyGenParameterSpec.F4))
|
||||
val keyPair: KeyPair = keyPairGenerator.generateKeyPair()
|
||||
|
||||
// 将公钥转换为X.509格式
|
||||
val x509EncodedPublicKey = keyPair.public.encoded
|
||||
val publicKeyString = Base64.encodeToString(x509EncodedPublicKey, Base64.NO_WRAP)
|
||||
|
||||
// 将私钥转换为PKCS#8格式
|
||||
val pkcs8EncodedPrivateKey = keyPair.private.encoded
|
||||
val privateKeyString = Base64.encodeToString(pkcs8EncodedPrivateKey, Base64.NO_WRAP)
|
||||
|
||||
return RSARandomKey(publicKeyString, privateKeyString)
|
||||
}
|
||||
|
||||
|
||||
// 默认是PKCS1,填充:(OAEP)RSA/ECB/OAEPWithSHA-1AndMGF1Padding或者(PKCS1)RSA/ECB/PKCS1Padding
|
||||
fun rsaEncrypt(input: String, publicKeyStr: String): String {
|
||||
val publicKey = stringToPublicKey(publicKeyStr)
|
||||
val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
|
||||
val encrypted = cipher.doFinal(input.toByteArray())
|
||||
return Base64.encodeToString(encrypted, Base64.NO_WRAP)
|
||||
|
||||
}
|
||||
// input是base64,PKCS1填充生成的加密内容
|
||||
fun rsaDecrypt(input: String, privateKeyStr: String): String {
|
||||
val privateKey = stringToPrivateKey(privateKeyStr)
|
||||
val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey)
|
||||
val decrypted = cipher.doFinal(Base64.decode(input, Base64.DEFAULT))
|
||||
return String(decrypted)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fun rc4Init(key: ByteArray): ByteArray {
|
||||
val s = ByteArray(256) { it.toByte() }
|
||||
var j = 0
|
||||
|
||||
for (i in 0..255) {
|
||||
j = (j + s[i].toInt() + key[i % key.size].toInt() and 0xFF) and 0xFF
|
||||
val temp = s[i]
|
||||
s[i] = s[j]
|
||||
s[j] = temp
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
fun rc4Process(data: ByteArray, key: ByteArray, outputLength: OutputLength): ByteArray {
|
||||
val s = rc4Init(key)
|
||||
val result = ByteArray(outputLength.length) // 使用指定的字节长度
|
||||
var i = 0
|
||||
var j = 0
|
||||
|
||||
for (n in result.indices) {
|
||||
i = (i + 1) and 0xFF
|
||||
j = (j + s[i].toInt() and 0xFF) and 0xFF
|
||||
|
||||
val temp = s[i]
|
||||
s[i] = s[j]
|
||||
s[j] = temp
|
||||
|
||||
val t = (s[i].toInt() + s[j].toInt() and 0xFF) and 0xFF
|
||||
val k = s[t].toInt() and 0xFF
|
||||
|
||||
result[n] = if (n < data.size) {
|
||||
(data[n].toInt() xor k).toByte()
|
||||
} else {
|
||||
k.toByte()
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
//输出是hex字符串,密钥是8位字符
|
||||
fun rc4Encrypt(data: String, key: String): String {
|
||||
val dataBytes = data.toByteArray()
|
||||
val keyBytes = key.toByteArray()
|
||||
val encrypted = rc4Process(dataBytes, keyBytes, OutputLength.LENGTH_16)
|
||||
return encrypted.joinToString("") { "%02x".format(it) }
|
||||
}
|
||||
//输入encryptedHex是hex字符串,返回是string,密钥是8位字符
|
||||
fun rc4Decrypt(encryptedHex: String, key: String): String {
|
||||
val encryptedBytes = encryptedHex.chunked(2)
|
||||
.map { it.toInt(16).toByte() }
|
||||
.toByteArray()
|
||||
val keyBytes = key.toByteArray()
|
||||
val decrypted = rc4Process(encryptedBytes, keyBytes, OutputLength.LENGTH_16)
|
||||
return decrypted.toString(Charset.defaultCharset()).trim('\u0000')
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import UniversalCryptoHelper from 'uts.sdk.modules.utsXcryptoS.UniversalCryptoHelper';
|
||||
import { RSARANDOMKEY } from "../interface.uts"
|
||||
|
||||
export function md5(str : string) : string {
|
||||
return UniversalCryptoHelper.md5(str);
|
||||
}
|
||||
export function base64Encode(str : string) : string {
|
||||
return UniversalCryptoHelper.base64Encode(str);
|
||||
}
|
||||
export function base64Decode(str : string) : string {
|
||||
return UniversalCryptoHelper.base64Decode(str);
|
||||
}
|
||||
export function sha256(str : string) : string {
|
||||
return UniversalCryptoHelper.sha256(str);
|
||||
}
|
||||
export function hmacSha256(key:string,data : string) : string {
|
||||
return UniversalCryptoHelper.hmacSha256(key,data);
|
||||
}
|
||||
|
||||
export function sha512(str : string) : string {
|
||||
return UniversalCryptoHelper.sha512(str)
|
||||
}
|
||||
|
||||
export function hmacSha512(key : string, data : string) : string {
|
||||
return UniversalCryptoHelper.hmacSha512(key,data)
|
||||
}
|
||||
|
||||
export function sha1(str : string) : string {
|
||||
return UniversalCryptoHelper.sha1(str);
|
||||
}
|
||||
/**
|
||||
* Aes
|
||||
* @param {string} key utf8字符串它会根据keySize来截取和补足0
|
||||
* @param {string} data 待加密的字符
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {string} iv 固定是16位,不足会补齐0
|
||||
* @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
*/
|
||||
export function aesEncrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null,keySize:number|null=null) : string {
|
||||
console.log("长度:",(keySize==null?16:keySize).toInt())
|
||||
return UniversalCryptoHelper.aesEncrypt(data,key,mode,iv,(keySize==null?16:keySize).toInt());
|
||||
}
|
||||
/**
|
||||
* Aes
|
||||
* @param {Uint8Array} key Uint8Array数据它会根据keySize来截取和补足0
|
||||
* @param {Uint8Array} data 待加密的Uint8Array
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {Uint8Array} iv 固定是16位,不足会补齐0
|
||||
* @param {number} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
* @returns {Uint8Array} 数据
|
||||
*/
|
||||
export function aesEncrypt2(key:Uint8Array,data : Uint8Array,mode:string = "ECB",iv:Uint8Array|null = null,keySize:number|null=null) : Uint8Array {
|
||||
|
||||
function u8tbr(d:Uint8Array):ByteArray{
|
||||
let bar = new ByteArray(d.length.toInt())
|
||||
for(let i = 0;i<d.length;i++){
|
||||
bar[i.toInt()] = d[i.toInt()].toByte()
|
||||
}
|
||||
return bar
|
||||
}
|
||||
function brtu8(d:ByteArray):Uint8Array{
|
||||
let bar = new Uint8Array(d.size)
|
||||
for(let i = 0;i<d.size;i++){
|
||||
bar[i.toInt()] = d[i.toInt()] & 0xFF
|
||||
}
|
||||
return bar
|
||||
}
|
||||
const result:ByteArray = UniversalCryptoHelper.aesEncrypt2(u8tbr(data),u8tbr(key),mode,iv==null?null:u8tbr(iv),(keySize==null?16:keySize).toInt());
|
||||
|
||||
return brtu8(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* DAes
|
||||
* @param {string} key utf8字符串它会根据keySize来截取和补足0
|
||||
* @param {string} data 加密后的base64的字符
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {string} iv 固定是16位,不足会补齐0
|
||||
* @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
*/
|
||||
export function aesDecrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null,keySize:number|null=null) : string {
|
||||
return UniversalCryptoHelper.aesDecrypt(data,key,mode,iv,(keySize==null?16:keySize).toInt());
|
||||
}
|
||||
export function aesDecrypt2(key:Uint8Array,data : Uint8Array,mode:string = "ECB",iv:Uint8Array|null = null,keySize:number|null=null) : Uint8Array {
|
||||
|
||||
function u8tbr(d:Uint8Array):ByteArray{
|
||||
let bar = new ByteArray(d.length.toInt())
|
||||
for(let i = 0;i<d.length;i++){
|
||||
bar[i.toInt()] = d[i.toInt()].toByte()
|
||||
}
|
||||
return bar
|
||||
}
|
||||
function brtu8(d:ByteArray):Uint8Array{
|
||||
let bar = new Uint8Array(d.size)
|
||||
for(let i = 0;i<d.size;i++){
|
||||
bar[i.toInt()] = d[i.toInt()] & 0xFF
|
||||
}
|
||||
return bar
|
||||
}
|
||||
const result:ByteArray = UniversalCryptoHelper.aesDecrypt2(u8tbr(data),u8tbr(key),mode,iv==null?null:u8tbr(iv),(keySize==null?16:keySize).toInt());
|
||||
|
||||
return brtu8(result);
|
||||
}
|
||||
|
||||
export function desEncrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null) : string {
|
||||
return UniversalCryptoHelper.desEncrypt(data,key,mode,iv);
|
||||
}
|
||||
export function desDecrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null) : string {
|
||||
return UniversalCryptoHelper.desDecrypt(data,key,mode,iv);
|
||||
}
|
||||
|
||||
// 获取公钥和私钥对
|
||||
export function generateRSAKeyPair(keySize : number = 2048) : RSARANDOMKEY {
|
||||
const crypt = UniversalCryptoHelper.generateRSAKeyPair(keySize.toInt())
|
||||
return {
|
||||
publicKey: crypt.publicKey,
|
||||
privateKey: crypt.privateKey
|
||||
} as RSARANDOMKEY
|
||||
}
|
||||
|
||||
export function rsaEncrypt(publicKey:string,data : string) : string {
|
||||
return UniversalCryptoHelper.rsaEncrypt(data,publicKey);
|
||||
}
|
||||
export function rsaDecrypt(privateKey:string,data : string) : string {
|
||||
return UniversalCryptoHelper.rsaDecrypt(data,privateKey);
|
||||
}
|
||||
//返回的是hex字符串
|
||||
export function rc4Encrypt(key:string,data : string) : string {
|
||||
return UniversalCryptoHelper.rc4Encrypt(data,key);
|
||||
}
|
||||
// key是hex字符
|
||||
export function rc4Decrypt(key:string,data : string) : string {
|
||||
return UniversalCryptoHelper.rc4Decrypt(data,key);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"x_crypto_s": "./lib/x_crypto_s.har"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { x_xCryptoS,X_RSARANDOMKEY } from "x_crypto_s";
|
||||
import { RSARANDOMKEY } from "../interface.uts";
|
||||
export function base64Encode(input : string) : string {
|
||||
return x_xCryptoS.base64Encode(input)
|
||||
}
|
||||
export function base64Decode(input : string) : string {
|
||||
return x_xCryptoS.base64Decode(input)
|
||||
}
|
||||
export function md5(input : string) : string {
|
||||
return x_xCryptoS.md5(input)
|
||||
}
|
||||
|
||||
export function sha256(str : string) : string {
|
||||
return x_xCryptoS.sha256(str)
|
||||
}
|
||||
export function sha512(str : string) : string {
|
||||
return x_xCryptoS.sha512(str)
|
||||
}
|
||||
export function hmacSha256(key : string, data : string) : string {
|
||||
return x_xCryptoS.hmacSha256(key,data)
|
||||
}
|
||||
|
||||
export function hmacSha512(key : string, data : string) : string {
|
||||
return x_xCryptoS.hmacSha512(key,data)
|
||||
}
|
||||
|
||||
export function sha1(str : string) : string {
|
||||
return x_xCryptoS.sha1(str)
|
||||
}
|
||||
/**
|
||||
* Aes
|
||||
* @param {string} key utf8字符串它会根据keySize来截取和补足0
|
||||
* @param {string} data 待加密的字符
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {string} iv 固定是16位,不足会补齐0
|
||||
* @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
*/
|
||||
export function aesEncrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null, keySize : number | null = 16) : string {
|
||||
return x_xCryptoS.aesEncrypt(key, data, mode, iv,keySize)
|
||||
}
|
||||
/**
|
||||
* DAes
|
||||
* @param {string} key utf8字符串它会根据keySize来截取和补足0
|
||||
* @param {string} data 加密后的base64的字符
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {string} iv 固定是16位,不足会补齐0
|
||||
* @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
*/
|
||||
export function aesDecrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null, keySize : number | null = 16) : string {
|
||||
return x_xCryptoS.aesDecrypt(key, data, mode, iv,keySize)
|
||||
}
|
||||
|
||||
export function aesEncrypt2(key : Uint8Array, data : Uint8Array, mode : string = "ECB", iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array {
|
||||
return x_xCryptoS.aesEncrypt2(key, data, mode, iv,keySize)
|
||||
}
|
||||
|
||||
export function aesDecrypt2(key : Uint8Array, data : Uint8Array, mode : string = "ECB", iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array {
|
||||
return x_xCryptoS.aesDecrypt2(key, data, mode, iv,keySize)
|
||||
}
|
||||
|
||||
export function desEncrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null) : string {
|
||||
return x_xCryptoS.desEncrypt(key, data, mode, iv)
|
||||
}
|
||||
|
||||
|
||||
export function desDecrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null) : string {
|
||||
return x_xCryptoS.desDecrypt(key, data, mode, iv)
|
||||
}
|
||||
|
||||
export function generateRSAKeyPair(keySize : number = 2048) : RSARANDOMKEY {
|
||||
const result:X_RSARANDOMKEY = x_xCryptoS.generateRSAKeyPair(keySize)
|
||||
return {
|
||||
publicKey: result.publicKey,
|
||||
privateKey: result.privateKey
|
||||
} as RSARANDOMKEY
|
||||
}
|
||||
export function rsaEncrypt(publicKey : string, data : string,keySize : number = 2048) : string {
|
||||
return x_xCryptoS.rsaEncrypt(publicKey, data,keySize)
|
||||
}
|
||||
export function rsaDecrypt(privateKey : string, data : string,keySize : number = 2048) : string {
|
||||
return x_xCryptoS.rsaDecrypt(privateKey, data,keySize)
|
||||
}
|
||||
//返回的是hex字符串
|
||||
export function rc4Encrypt(key : string, data : string) : string {
|
||||
return x_xCryptoS.rc4Encrypt(key, data)
|
||||
}
|
||||
|
||||
// key是hex字符
|
||||
export function rc4Decrypt(key : string, data : string) : string {
|
||||
return x_xCryptoS.rc4Decrypt(key, data)
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyTrackingDomains</key>
|
||||
<array/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,212 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>Headers/unimoduleXCryptoS-Swift.h</key>
|
||||
<data>
|
||||
sYrSn+RyBIFDQBszO3/P8xJljp8=
|
||||
</data>
|
||||
<key>Headers/unimoduleXCryptoS.h</key>
|
||||
<data>
|
||||
FH2SRnQAHIO8AbDZPa5/Bz/CcdA=
|
||||
</data>
|
||||
<key>Info.plist</key>
|
||||
<data>
|
||||
IVoTM86XmFTSTQOc3nqKLlrf+g4=
|
||||
</data>
|
||||
<key>Modules/module.modulemap</key>
|
||||
<data>
|
||||
Mb2Zqns/19tDjbGpiH3LGGA1fQA=
|
||||
</data>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo</key>
|
||||
<data>
|
||||
LrNVXN9SxWbowabgwHEhjXGtoM8=
|
||||
</data>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
|
||||
<data>
|
||||
u+u1y6eK8UyQLdXF+asiH9J61zw=
|
||||
</data>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
|
||||
<data>
|
||||
TBpJmMJe82pwDjT2PuqjFG0QOgo=
|
||||
</data>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
|
||||
<data>
|
||||
vAWogVlQ2acSpes+rngJqaHu53s=
|
||||
</data>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
|
||||
<data>
|
||||
TBpJmMJe82pwDjT2PuqjFG0QOgo=
|
||||
</data>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
|
||||
<data>
|
||||
DYmcbJn2Wta9ChJfVGlUIOckdl0=
|
||||
</data>
|
||||
<key>config.json</key>
|
||||
<data>
|
||||
/sqVTWYkSC3IKjeGGZtJQnx8PC0=
|
||||
</data>
|
||||
</dict>
|
||||
<key>files2</key>
|
||||
<dict>
|
||||
<key>Headers/unimoduleXCryptoS-Swift.h</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
bTRltszQF3+fsDE5fSoWA2h4RJFMjgJiooCIolmygdk=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/unimoduleXCryptoS.h</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
XAsze1m7Z4PhyI2gj+RafZVS4xyqWjgvqraTawdVPMY=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/module.modulemap</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
W0XF/xxiculnRfXzfkaeT5qgc+qCLcZzsOzHUDmxshc=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
l63MWC0FBuCg1jbWMzXhOYlbdgWWib9kANlDZQDhvOQ=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
LjfbpG0RJlR1dLq/DxB3kwt6X4B0pQQmnw5Obt8VOhU=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
tYzzmU2An+2B2UBi/H0Qkz+BkR6fVGyq0IKlEcdMCxk=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
NXc6efR/rQre4hYKBGOWCStcK9AsMK9pnXXvCFoiq4c=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
tYzzmU2An+2B2UBi/H0Qkz+BkR6fVGyq0IKlEcdMCxk=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/unimoduleXCryptoS.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
NAmTbjwY/t547ARB7gCdhKUdLuBnd/8815n5YixIHB8=
|
||||
</data>
|
||||
</dict>
|
||||
<key>config.json</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
aW1+rl6/vnHObZ31RQBG9uwopiZhbmvup1CuOkP3aZo=
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"deploymentTarget": "12",
|
||||
"dependencies-pods": [
|
||||
{
|
||||
"name": "CryptoSwift",
|
||||
"version": "1.8.3"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import Foundation, { Data, JSONDecoder, NSNumber } from 'Foundation'
|
||||
import { CryptoKit, SymmetricKey } from 'CryptoKit'
|
||||
import CommonCrypto from 'CommonCrypto'
|
||||
import { UInt8, UnsafeRawBufferPointer , Int } from "Swift";
|
||||
import { RSARANDOMKEY } from "../interface.uts"
|
||||
|
||||
|
||||
|
||||
export function md5(str : string) : string {
|
||||
return UniversalCryptoHelper.md5(input = str);
|
||||
}
|
||||
export function base64Encode(str : string) : string {
|
||||
return UniversalCryptoHelper.base64Encode(input = str);
|
||||
}
|
||||
export function base64Decode(str : string) : string {
|
||||
return UniversalCryptoHelper.base64Decode(input = str);
|
||||
}
|
||||
export function sha256(str : string) : string {
|
||||
return UniversalCryptoHelper.sha256(input = str);
|
||||
}
|
||||
export function sha512(str : string) : string {
|
||||
return UniversalCryptoHelper.sha512(input = str);
|
||||
}
|
||||
export function hmacSha256(key:string,data : string) : string {
|
||||
return UniversalCryptoHelper.hmacSha256(key = key,data = data);
|
||||
}
|
||||
export function hmacSha512(key:string,data : string) : string {
|
||||
return UniversalCryptoHelper.hmacSha512(key = key,data = data);
|
||||
}
|
||||
export function sha1(str : string) : string {
|
||||
return UniversalCryptoHelper.sha1(input = str);
|
||||
}
|
||||
export function aesEncrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null,keySize:number|null=null) : string {
|
||||
return UniversalCryptoHelper.aesEncrypt(input = data,key = key,mode = mode,iv = iv,keySize = (keySize==null?16:keySize!).toInt());
|
||||
}
|
||||
export function aesDecrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null,keySize:number|null=null) : string {
|
||||
return UniversalCryptoHelper.aesDecrypt(input = data,key = key,mode = mode,iv = iv,keySize=(keySize==null?16:keySize!).toInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* AES加密 - ArrayBuffer版本
|
||||
* @param {ArrayBuffer} key ArrayBuffer数据它会根据keySize来截取和补足0
|
||||
* @param {ArrayBuffer} data 待加密的ArrayBuffer
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {ArrayBuffer} iv 固定是16位,不足会补齐0
|
||||
* @param {number} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
* @returns {number[]} 加密后的数据
|
||||
*/
|
||||
export function aesEncrypt2(key:ArrayBuffer,data : ArrayBuffer,mode:string = "ECB",iv:ArrayBuffer|null = null,keySize:number|null=null) : number[] {
|
||||
|
||||
const keyArray = key.toData()
|
||||
const dataArray = data.toData()
|
||||
const ivArray = (iv == null ? null :iv.toData()) as Data|null;
|
||||
const result = UniversalCryptoHelper.aesEncrypt2(input = dataArray, key = keyArray, mode = mode, iv = ivArray, keySize = (keySize==null?16:keySize!).toInt())
|
||||
|
||||
let resuitAr:number[] = result.bytes.map((el:UInt8):number=> NSNumber.from(new Int(el)))
|
||||
return resuitAr
|
||||
}
|
||||
|
||||
/**
|
||||
* AES解密 - ArrayBuffer版本
|
||||
* @param {ArrayBuffer} key ArrayBuffer数据它会根据keySize来截取和补足0
|
||||
* @param {ArrayBuffer} data 待解密的ArrayBuffer
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {ArrayBuffer} iv 固定是16位,不足会补齐0
|
||||
* @param {number} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
* @returns {number[]} 解密后的数据
|
||||
*/
|
||||
export function aesDecrypt2(key:ArrayBuffer,data : ArrayBuffer,mode:string = "ECB",iv:ArrayBuffer|null = null,keySize:number|null=null) : number[] {
|
||||
const keyArray = key.toData()
|
||||
const dataArray = data.toData()
|
||||
const ivArray = (iv == null ? null :iv.toData()) as Data|null;
|
||||
|
||||
const result = UniversalCryptoHelper.aesDecrypt2(input = dataArray, key = keyArray, mode = mode, iv = ivArray, keySize = (keySize==null?16:keySize!).toInt())
|
||||
let resuitAr:number[] = result.bytes.map((el:UInt8):number=> NSNumber.from(new Int(el)))
|
||||
return resuitAr
|
||||
}
|
||||
export function desEncrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null) : string {
|
||||
return UniversalCryptoHelper.desEncrypt(input = data,key = key,mode=mode,iv=iv);
|
||||
}
|
||||
export function desDecrypt(key:string,data : string,mode:string = "ECB",iv:string|null = null) : string {
|
||||
return UniversalCryptoHelper.desDecrypt(input = data,key = key,mode=mode,iv=iv);
|
||||
}
|
||||
export function generateRSAKeyPair(keySize : number = 2048) : RSARANDOMKEY {
|
||||
const crypt = UTSiOS.try(UniversalCryptoHelper.generateRSAKeyPair(keySize = keySize.toInt()),"?")
|
||||
|
||||
if(crypt==null){
|
||||
return {
|
||||
publicKey: "",
|
||||
privateKey: "",
|
||||
} as RSARANDOMKEY
|
||||
}
|
||||
return {
|
||||
publicKey: crypt!.publicKey,
|
||||
privateKey: crypt!.privateKey
|
||||
} as RSARANDOMKEY
|
||||
}
|
||||
|
||||
export function rsaEncrypt(publicKey:string,data : string) : string {
|
||||
const crypt = UTSiOS.try(UniversalCryptoHelper.rsaEncrypt(data,publicKey = publicKey),"?")
|
||||
// return UniversalCryptoHelper.rsaEncrypt(input = data,publicKey = publicKey);
|
||||
if(crypt==null) return ""
|
||||
return crypt!;
|
||||
}
|
||||
|
||||
export function rsaDecrypt(privateKey:string,data : string) : string {
|
||||
const crypt = UTSiOS.try(UniversalCryptoHelper.rsaDecrypt(data,privateKey = privateKey),"?")
|
||||
if(crypt==null) return ""
|
||||
// return UniversalCryptoHelper.rsaDecrypt(input = data,privateKey = privateKey);
|
||||
return crypt!;
|
||||
}
|
||||
//返回的是hex字符串
|
||||
export function rc4Encrypt(key:string,data : string) : string {
|
||||
return UniversalCryptoHelper.rc4Encrypt(data = data,key = key);
|
||||
}
|
||||
|
||||
// key是hex字符
|
||||
export function rc4Decrypt(key:string,data : string) : string {
|
||||
return UniversalCryptoHelper.rc4Decrypt(encryptedHex = data,key = key);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
export type SQLiteConfig = {
|
||||
password?: string;
|
||||
encryption?: boolean;
|
||||
locateFile?: (filename: string) => string;
|
||||
}
|
||||
|
||||
export type SQLiteResult = {
|
||||
rows?: any[][];
|
||||
columns?: string[];
|
||||
changes?: number;
|
||||
lastInsertRowid?: number;
|
||||
error?: string;
|
||||
}
|
||||
export type SQLiteExecuteBatchParams = {
|
||||
sql:string,
|
||||
params?:any[]
|
||||
}
|
||||
export type RSARANDOMKEY = {
|
||||
publicKey: string,
|
||||
privateKey: string
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
import CryptoJS from "./lib/index.js"
|
||||
import { JSEncrypt } from "./src/JSEncrypt"
|
||||
export { RSARANDOMKEY } from "../interface.uts"
|
||||
|
||||
function adjustIV(ivStr, requiredLength = 16) {
|
||||
// 将字符串转换为字节
|
||||
let ivBytes = CryptoJS.enc.Utf8.parse(ivStr);
|
||||
// 创建一个新的WordArray来存储处理后的IV
|
||||
let adjustedIV = CryptoJS.lib.WordArray.create();
|
||||
|
||||
if (ivBytes.sigBytes >= requiredLength) {
|
||||
// 如果IV长度足够或过长,进行截取
|
||||
adjustedIV = CryptoJS.lib.WordArray.create(ivBytes.words.slice(0, requiredLength / 4));
|
||||
} else {
|
||||
// 如果IV长度不足,进行补足0
|
||||
adjustedIV = CryptoJS.lib.WordArray.create(ivBytes.words);
|
||||
for (let i = ivBytes.sigBytes / 4; i < requiredLength / 4; i++) {
|
||||
adjustedIV.words[i] = 0;
|
||||
}
|
||||
adjustedIV.sigBytes = requiredLength;
|
||||
}
|
||||
|
||||
return adjustedIV;
|
||||
}
|
||||
|
||||
|
||||
function adjustIV2(ivStr:Uint8Array, requiredLength = 16) {
|
||||
// 确保密钥长度为requiredLength字节,不足时用0填充,过长时截断
|
||||
const paddedKey = new Uint8Array(requiredLength);
|
||||
if (ivStr.length < requiredLength) {
|
||||
paddedKey.set(ivStr, 0);
|
||||
} else {
|
||||
paddedKey.set(ivStr.slice(0, requiredLength), 0);
|
||||
}
|
||||
|
||||
// 将Uint8Array转换为WordArray
|
||||
const words:number[] = [];
|
||||
for (let i = 0; i < paddedKey.length; i += 4) {
|
||||
let word = 0;
|
||||
for (let j = 0; j < 4 && i + j < paddedKey.length; j++) {
|
||||
word |= paddedKey[i + j] << (24 - j * 8);
|
||||
}
|
||||
words.push(word);
|
||||
}
|
||||
return CryptoJS.lib.WordArray.create(words, paddedKey.length);
|
||||
}
|
||||
|
||||
export function base64Encode(input : string) : string {
|
||||
return CryptoJS.enc.Utf8.parse(input).toString(CryptoJS.enc.Base64)
|
||||
}
|
||||
export function base64Decode(input : string) : string {
|
||||
return CryptoJS.enc.Base64.parse(input).toString(CryptoJS.enc.Utf8)
|
||||
}
|
||||
export function md5(input : string) : string {
|
||||
return CryptoJS.MD5(input).toString()
|
||||
}
|
||||
|
||||
export function sha256(str : string) : string {
|
||||
return CryptoJS.SHA256(str).toString()
|
||||
}
|
||||
export function sha512(str : string) : string {
|
||||
return CryptoJS.SHA512(str).toString()
|
||||
}
|
||||
export function hmacSha256(key : string, data : string) : string {
|
||||
return CryptoJS.HmacSHA256(data, key).toString()
|
||||
}
|
||||
|
||||
export function hmacSha512(key : string, data : string) : string {
|
||||
return CryptoJS.HmacSHA512(data, key).toString()
|
||||
}
|
||||
|
||||
export function sha1(str : string) : string {
|
||||
return CryptoJS.SHA1(str).toString()
|
||||
}
|
||||
/**
|
||||
* Aes
|
||||
* @param {string} key utf8字符串它会根据keySize来截取和补足0
|
||||
* @param {string} data 待加密的字符
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {string} iv 固定是16位,不足会补齐0
|
||||
* @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
*/
|
||||
export function aesEncrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null, keySize : number | null = 16) : string {
|
||||
const keyData = adjustIV(key, keySize || 16);
|
||||
const ivValue = adjustIV(iv || "");
|
||||
let word = CryptoJS.AES.encrypt(data, keyData, {
|
||||
iv: ivValue,
|
||||
mode: CryptoJS.mode[mode],
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
return word.toString()
|
||||
}
|
||||
/**
|
||||
* DAes
|
||||
* @param {string} key utf8字符串它会根据keySize来截取和补足0
|
||||
* @param {string} data 加密后的base64的字符
|
||||
* @param {string} mode ECB,CBC
|
||||
* @param {string} iv 固定是16位,不足会补齐0
|
||||
* @param {string} keySize 对key的加密补位,也就是加密位数16为128,24为192,32为256
|
||||
*/
|
||||
export function aesDecrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null, keySize : number | null = 16) : string {
|
||||
const keyData = adjustIV(key, keySize || 16);
|
||||
const ivValue = adjustIV(iv || "");
|
||||
|
||||
let word = CryptoJS.AES.decrypt(data, keyData, { iv: ivValue, mode: CryptoJS.mode[mode], padding: CryptoJS.pad.Pkcs7 });
|
||||
return word.toString(CryptoJS.enc.Utf8)
|
||||
}
|
||||
|
||||
export function aesEncrypt2(key : Uint8Array, data : Uint8Array, mode : string = "ECB", iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array {
|
||||
const keyData = adjustIV2(key, keySize || 16);
|
||||
|
||||
// 将数据转换为WordArray
|
||||
const words:number[] = [];
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
let word = 0;
|
||||
for (let j = 0; j < 4 && i + j < data.length; j++) {
|
||||
word |= data[i + j] << (24 - j * 8);
|
||||
}
|
||||
words.push(word);
|
||||
}
|
||||
const dataU8 = CryptoJS.lib.WordArray.create(words, data.length);
|
||||
|
||||
// 处理IV
|
||||
let ivValue:any;
|
||||
if (mode === "ECB") {
|
||||
ivValue = CryptoJS.lib.WordArray.create([]);
|
||||
} else {
|
||||
const ivData = iv || new Uint8Array(16);
|
||||
ivValue = adjustIV2(ivData, 16);
|
||||
}
|
||||
|
||||
let word = CryptoJS.AES.encrypt(dataU8, keyData, {
|
||||
iv: ivValue,
|
||||
mode: CryptoJS.mode[mode],
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
// 正确地将WordArray转换为Uint8Array
|
||||
// @ts-ignore
|
||||
const resultWords = word.ciphertext.words;
|
||||
// @ts-ignore
|
||||
const sigBytes = word.ciphertext.sigBytes;
|
||||
const result = new Uint8Array(sigBytes);
|
||||
|
||||
for (let i = 0; i < sigBytes; i++) {
|
||||
const wordIndex = Math.floor(i / 4);
|
||||
const byteIndex = i % 4;
|
||||
result[i] = (resultWords[wordIndex] >>> (24 - byteIndex * 8)) & 0xff;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function aesDecrypt2(key : Uint8Array, data : Uint8Array, mode : string = "ECB", iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array {
|
||||
const keyData = adjustIV2(key, keySize || 16);
|
||||
|
||||
// 处理IV
|
||||
let ivValue:any;
|
||||
if (mode === "ECB") {
|
||||
ivValue = CryptoJS.lib.WordArray.create([]);
|
||||
} else {
|
||||
const ivData = iv || new Uint8Array(16);
|
||||
ivValue = adjustIV2(ivData, 16);
|
||||
}
|
||||
|
||||
// 将加密数据转换为WordArray
|
||||
const words:number[] = [];
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
let word = 0;
|
||||
for (let j = 0; j < 4 && i + j < data.length; j++) {
|
||||
word |= data[i + j] << (24 - j * 8);
|
||||
}
|
||||
words.push(word);
|
||||
}
|
||||
const cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
ciphertext: CryptoJS.lib.WordArray.create(words, data.length)
|
||||
});
|
||||
|
||||
let word = CryptoJS.AES.decrypt(cipherParams, keyData, { iv: ivValue, mode: CryptoJS.mode[mode], padding: CryptoJS.pad.Pkcs7 });
|
||||
|
||||
// 正确地将WordArray转换为Uint8Array
|
||||
const resultWords = word.words;
|
||||
const sigBytes = word.sigBytes;
|
||||
const result = new Uint8Array(sigBytes);
|
||||
|
||||
for (let i = 0; i < sigBytes; i++) {
|
||||
const wordIndex = Math.floor(i / 4);
|
||||
const byteIndex = i % 4;
|
||||
result[i] = (resultWords[wordIndex] >>> (24 - byteIndex * 8)) & 0xff;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
export function desEncrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null) : string {
|
||||
let word = CryptoJS.DES.encrypt(data, key, { iv: CryptoJS.enc.Utf8.parse(iv || ""), mode: CryptoJS.mode[mode] });
|
||||
return word.toString()
|
||||
}
|
||||
export function desDecrypt(key : string, data : string, mode : string = "ECB", iv : string | null = null) : string {
|
||||
let word = CryptoJS.DES.decrypt(data, key, { iv: CryptoJS.enc.Utf8.parse(iv || ""), mode: CryptoJS.mode[mode] });
|
||||
return word.toString(CryptoJS.enc.Utf8)
|
||||
}
|
||||
|
||||
export function generateRSAKeyPair(keySize : number = 2048) : RSARANDOMKEY {
|
||||
const crypt = new JSEncrypt({ default_key_size: keySize.toString() })
|
||||
crypt.getKey()
|
||||
return {
|
||||
publicKey: crypt.getPublicKey(),
|
||||
privateKey: crypt.getPrivateKey()
|
||||
} as RSARANDOMKEY
|
||||
}
|
||||
|
||||
export function rsaEncrypt(publicKey : string, data : string) : string {
|
||||
JSEncrypt.prototype.setPublicKey(publicKey)
|
||||
return JSEncrypt.prototype.encrypt(data) || ""
|
||||
}
|
||||
export function rsaDecrypt(privateKey : string, data : string) : string {
|
||||
JSEncrypt.prototype.setPrivateKey(privateKey)
|
||||
return JSEncrypt.prototype.decrypt(data) || ""
|
||||
}
|
||||
//返回的是hex字符串
|
||||
export function rc4Encrypt(key : string, data : string) : string {
|
||||
return CryptoJS.RC4.encrypt(data, CryptoJS.enc.Utf8.parse(key)).toString(CryptoJS.format.Hex)
|
||||
}
|
||||
|
||||
// key是hex字符
|
||||
export function rc4Decrypt(key : string, data : string) : string {
|
||||
const ciphertext = CryptoJS.enc.Hex.parse(data);
|
||||
let dec = CryptoJS.RC4.decrypt({ ciphertext: ciphertext }, CryptoJS.enc.Utf8.parse(key))
|
||||
return dec.toString(CryptoJS.enc.Utf8);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* AES block cipher algorithm.
|
||||
*/
|
||||
export class AESAlgo extends BlockCipher {
|
||||
}
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const AES: CipherObj;
|
||||
import { CipherObj } from './cipher-core.js';
|
||||
import { BlockCipher } from './cipher-core.js';
|
||||
@@ -0,0 +1,278 @@
|
||||
import {
|
||||
BlockCipher,
|
||||
} from './cipher-core.js';
|
||||
|
||||
// Lookup tables
|
||||
const _SBOX = [];
|
||||
const INV_SBOX = [];
|
||||
const _SUB_MIX_0 = [];
|
||||
const _SUB_MIX_1 = [];
|
||||
const _SUB_MIX_2 = [];
|
||||
const _SUB_MIX_3 = [];
|
||||
const INV_SUB_MIX_0 = [];
|
||||
const INV_SUB_MIX_1 = [];
|
||||
const INV_SUB_MIX_2 = [];
|
||||
const INV_SUB_MIX_3 = [];
|
||||
|
||||
// Compute lookup tables
|
||||
|
||||
// Compute double table
|
||||
const d = [];
|
||||
for (let i = 0; i < 256; i += 1) {
|
||||
if (i < 128) {
|
||||
d[i] = i << 1;
|
||||
} else {
|
||||
d[i] = (i << 1) ^ 0x11b;
|
||||
}
|
||||
}
|
||||
|
||||
// Walk GF(2^8)
|
||||
let x = 0;
|
||||
let xi = 0;
|
||||
for (let i = 0; i < 256; i += 1) {
|
||||
// Compute sbox
|
||||
let sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
|
||||
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
|
||||
_SBOX[x] = sx;
|
||||
INV_SBOX[sx] = x;
|
||||
|
||||
// Compute multiplication
|
||||
const x2 = d[x];
|
||||
const x4 = d[x2];
|
||||
const x8 = d[x4];
|
||||
|
||||
// Compute sub bytes, mix columns tables
|
||||
let t = (d[sx] * 0x101) ^ (sx * 0x1010100);
|
||||
_SUB_MIX_0[x] = (t << 24) | (t >>> 8);
|
||||
_SUB_MIX_1[x] = (t << 16) | (t >>> 16);
|
||||
_SUB_MIX_2[x] = (t << 8) | (t >>> 24);
|
||||
_SUB_MIX_3[x] = t;
|
||||
|
||||
// Compute inv sub bytes, inv mix columns tables
|
||||
t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
|
||||
INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
|
||||
INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
|
||||
INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24);
|
||||
INV_SUB_MIX_3[sx] = t;
|
||||
|
||||
// Compute next counter
|
||||
if (!x) {
|
||||
xi = 1;
|
||||
x = xi;
|
||||
} else {
|
||||
x = x2 ^ d[d[d[x8 ^ x2]]];
|
||||
xi ^= d[d[xi]];
|
||||
}
|
||||
}
|
||||
|
||||
// Precomputed Rcon lookup
|
||||
const RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
|
||||
|
||||
/**
|
||||
* AES block cipher algorithm.
|
||||
*/
|
||||
export class AESAlgo extends BlockCipher {
|
||||
_doReset() {
|
||||
let t;
|
||||
|
||||
// Skip reset of nRounds has been set before and key did not change
|
||||
if (this._nRounds && this._keyPriorReset === this._key) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
this._keyPriorReset = this._key;
|
||||
const key = this._keyPriorReset;
|
||||
const keyWords = key.words;
|
||||
const keySize = key.sigBytes / 4;
|
||||
|
||||
// Compute number of rounds
|
||||
this._nRounds = keySize + 6;
|
||||
const nRounds = this._nRounds;
|
||||
|
||||
// Compute number of key schedule rows
|
||||
const ksRows = (nRounds + 1) * 4;
|
||||
|
||||
// Compute key schedule
|
||||
this._keySchedule = [];
|
||||
const keySchedule = this._keySchedule;
|
||||
for (let ksRow = 0; ksRow < ksRows; ksRow += 1) {
|
||||
if (ksRow < keySize) {
|
||||
keySchedule[ksRow] = keyWords[ksRow];
|
||||
} else {
|
||||
t = keySchedule[ksRow - 1];
|
||||
|
||||
if (!(ksRow % keySize)) {
|
||||
// Rot word
|
||||
t = (t << 8) | (t >>> 24);
|
||||
|
||||
// Sub word
|
||||
t = (_SBOX[t >>> 24] << 24)
|
||||
| (_SBOX[(t >>> 16) & 0xff] << 16)
|
||||
| (_SBOX[(t >>> 8) & 0xff] << 8)
|
||||
| _SBOX[t & 0xff];
|
||||
|
||||
// Mix Rcon
|
||||
t ^= RCON[(ksRow / keySize) | 0] << 24;
|
||||
} else if (keySize > 6 && ksRow % keySize === 4) {
|
||||
// Sub word
|
||||
t = (_SBOX[t >>> 24] << 24)
|
||||
| (_SBOX[(t >>> 16) & 0xff] << 16)
|
||||
| (_SBOX[(t >>> 8) & 0xff] << 8)
|
||||
| _SBOX[t & 0xff];
|
||||
}
|
||||
|
||||
keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute inv key schedule
|
||||
this._invKeySchedule = [];
|
||||
const invKeySchedule = this._invKeySchedule;
|
||||
for (let invKsRow = 0; invKsRow < ksRows; invKsRow += 1) {
|
||||
const ksRow = ksRows - invKsRow;
|
||||
|
||||
if (invKsRow % 4) {
|
||||
t = keySchedule[ksRow];
|
||||
} else {
|
||||
t = keySchedule[ksRow - 4];
|
||||
}
|
||||
|
||||
if (invKsRow < 4 || ksRow <= 4) {
|
||||
invKeySchedule[invKsRow] = t;
|
||||
} else {
|
||||
invKeySchedule[invKsRow] = INV_SUB_MIX_0[_SBOX[t >>> 24]]
|
||||
^ INV_SUB_MIX_1[_SBOX[(t >>> 16) & 0xff]]
|
||||
^ INV_SUB_MIX_2[_SBOX[(t >>> 8) & 0xff]]
|
||||
^ INV_SUB_MIX_3[_SBOX[t & 0xff]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
encryptBlock(M, offset) {
|
||||
this._doCryptBlock(
|
||||
M, offset, this._keySchedule, _SUB_MIX_0, _SUB_MIX_1, _SUB_MIX_2, _SUB_MIX_3, _SBOX,
|
||||
);
|
||||
}
|
||||
|
||||
decryptBlock(M, offset) {
|
||||
const _M = M;
|
||||
|
||||
// Swap 2nd and 4th rows
|
||||
let t = _M[offset + 1];
|
||||
_M[offset + 1] = _M[offset + 3];
|
||||
_M[offset + 3] = t;
|
||||
|
||||
this._doCryptBlock(
|
||||
_M,
|
||||
offset,
|
||||
this._invKeySchedule,
|
||||
INV_SUB_MIX_0,
|
||||
INV_SUB_MIX_1,
|
||||
INV_SUB_MIX_2,
|
||||
INV_SUB_MIX_3,
|
||||
INV_SBOX,
|
||||
);
|
||||
|
||||
// Inv swap 2nd and 4th rows
|
||||
t = _M[offset + 1];
|
||||
_M[offset + 1] = _M[offset + 3];
|
||||
_M[offset + 3] = t;
|
||||
}
|
||||
|
||||
_doCryptBlock(M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
|
||||
const _M = M;
|
||||
|
||||
// Shortcut
|
||||
const nRounds = this._nRounds;
|
||||
|
||||
// Get input, add round key
|
||||
let s0 = _M[offset] ^ keySchedule[0];
|
||||
let s1 = _M[offset + 1] ^ keySchedule[1];
|
||||
let s2 = _M[offset + 2] ^ keySchedule[2];
|
||||
let s3 = _M[offset + 3] ^ keySchedule[3];
|
||||
|
||||
// Key schedule row counter
|
||||
let ksRow = 4;
|
||||
|
||||
// Rounds
|
||||
for (let round = 1; round < nRounds; round += 1) {
|
||||
// Shift rows, sub bytes, mix columns, add round key
|
||||
const t0 = SUB_MIX_0[s0 >>> 24]
|
||||
^ SUB_MIX_1[(s1 >>> 16) & 0xff]
|
||||
^ SUB_MIX_2[(s2 >>> 8) & 0xff]
|
||||
^ SUB_MIX_3[s3 & 0xff]
|
||||
^ keySchedule[ksRow];
|
||||
ksRow += 1;
|
||||
const t1 = SUB_MIX_0[s1 >>> 24]
|
||||
^ SUB_MIX_1[(s2 >>> 16) & 0xff]
|
||||
^ SUB_MIX_2[(s3 >>> 8) & 0xff]
|
||||
^ SUB_MIX_3[s0 & 0xff]
|
||||
^ keySchedule[ksRow];
|
||||
ksRow += 1;
|
||||
const t2 = SUB_MIX_0[s2 >>> 24]
|
||||
^ SUB_MIX_1[(s3 >>> 16) & 0xff]
|
||||
^ SUB_MIX_2[(s0 >>> 8) & 0xff]
|
||||
^ SUB_MIX_3[s1 & 0xff]
|
||||
^ keySchedule[ksRow];
|
||||
ksRow += 1;
|
||||
const t3 = SUB_MIX_0[s3 >>> 24]
|
||||
^ SUB_MIX_1[(s0 >>> 16) & 0xff]
|
||||
^ SUB_MIX_2[(s1 >>> 8) & 0xff]
|
||||
^ SUB_MIX_3[s2 & 0xff]
|
||||
^ keySchedule[ksRow];
|
||||
ksRow += 1;
|
||||
|
||||
// Update state
|
||||
s0 = t0;
|
||||
s1 = t1;
|
||||
s2 = t2;
|
||||
s3 = t3;
|
||||
}
|
||||
|
||||
// Shift rows, sub bytes, add round key
|
||||
const t0 = (
|
||||
(SBOX[s0 >>> 24] << 24)
|
||||
| (SBOX[(s1 >>> 16) & 0xff] << 16)
|
||||
| (SBOX[(s2 >>> 8) & 0xff] << 8)
|
||||
| SBOX[s3 & 0xff]
|
||||
) ^ keySchedule[ksRow];
|
||||
ksRow += 1;
|
||||
const t1 = (
|
||||
(SBOX[s1 >>> 24] << 24)
|
||||
| (SBOX[(s2 >>> 16) & 0xff] << 16)
|
||||
| (SBOX[(s3 >>> 8) & 0xff] << 8)
|
||||
| SBOX[s0 & 0xff]
|
||||
) ^ keySchedule[ksRow];
|
||||
ksRow += 1;
|
||||
const t2 = (
|
||||
(SBOX[s2 >>> 24] << 24)
|
||||
| (SBOX[(s3 >>> 16) & 0xff] << 16)
|
||||
| (SBOX[(s0 >>> 8) & 0xff] << 8)
|
||||
| SBOX[s1 & 0xff]
|
||||
) ^ keySchedule[ksRow];
|
||||
ksRow += 1;
|
||||
const t3 = (
|
||||
(SBOX[s3 >>> 24] << 24)
|
||||
| (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]
|
||||
) ^ keySchedule[ksRow];
|
||||
ksRow += 1;
|
||||
|
||||
// Set output
|
||||
_M[offset] = t0;
|
||||
_M[offset + 1] = t1;
|
||||
_M[offset + 2] = t2;
|
||||
_M[offset + 3] = t3;
|
||||
}
|
||||
}
|
||||
AESAlgo.keySize = 256 / 32;
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const AES = BlockCipher._createHelper(AESAlgo);
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Blowfish block cipher algorithm.
|
||||
*/
|
||||
export class BlowfishAlgo extends BlockCipher {
|
||||
}
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const Blowfish: CipherObj;
|
||||
import { CipherObj } from './cipher-core.js';
|
||||
import { BlockCipher } from './cipher-core.js';
|
||||
@@ -0,0 +1,446 @@
|
||||
import {
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
import {
|
||||
BlockCipher,
|
||||
} from './cipher-core.js';
|
||||
|
||||
const N = 16;
|
||||
|
||||
//Origin pbox and sbox, derived from PI
|
||||
const ORIG_P = [
|
||||
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
|
||||
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
|
||||
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
|
||||
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
|
||||
0x9216D5D9, 0x8979FB1B,
|
||||
];
|
||||
|
||||
const ORIG_S = [
|
||||
[0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
|
||||
0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
|
||||
0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
|
||||
0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
|
||||
0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
|
||||
0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
|
||||
0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
|
||||
0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
|
||||
0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
|
||||
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
|
||||
0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
|
||||
0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
|
||||
0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
|
||||
0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
|
||||
0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
|
||||
0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
|
||||
0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
|
||||
0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
|
||||
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
|
||||
0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
|
||||
0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
|
||||
0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
|
||||
0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
|
||||
0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
|
||||
0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
|
||||
0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
|
||||
0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
|
||||
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
|
||||
0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
|
||||
0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
|
||||
0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
|
||||
0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
|
||||
0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
|
||||
0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
|
||||
0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
|
||||
0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
|
||||
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
|
||||
0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
|
||||
0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
|
||||
0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
|
||||
0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
|
||||
0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
|
||||
0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
|
||||
0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
|
||||
0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
|
||||
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
|
||||
0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
|
||||
0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
|
||||
0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
|
||||
0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
|
||||
0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
|
||||
0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
|
||||
0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
|
||||
0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
|
||||
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
|
||||
0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
|
||||
0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
|
||||
0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
|
||||
0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
|
||||
0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
|
||||
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
|
||||
0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
|
||||
0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
|
||||
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A,],
|
||||
[0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
|
||||
0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
|
||||
0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
|
||||
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
|
||||
0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
|
||||
0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
|
||||
0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
|
||||
0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
|
||||
0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
|
||||
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
|
||||
0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
|
||||
0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
|
||||
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
|
||||
0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
|
||||
0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
|
||||
0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
|
||||
0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
|
||||
0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
|
||||
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
|
||||
0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
|
||||
0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
|
||||
0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
|
||||
0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
|
||||
0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
|
||||
0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
|
||||
0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
|
||||
0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
|
||||
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
|
||||
0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
|
||||
0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
|
||||
0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
|
||||
0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
|
||||
0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
|
||||
0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
|
||||
0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
|
||||
0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
|
||||
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
|
||||
0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
|
||||
0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
|
||||
0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
|
||||
0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
|
||||
0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
|
||||
0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
|
||||
0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
|
||||
0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
|
||||
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
|
||||
0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
|
||||
0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
|
||||
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
|
||||
0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
|
||||
0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
|
||||
0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
|
||||
0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
|
||||
0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
|
||||
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
|
||||
0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
|
||||
0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
|
||||
0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
|
||||
0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
|
||||
0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
|
||||
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
|
||||
0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
|
||||
0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
|
||||
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7,],
|
||||
[0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
|
||||
0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
|
||||
0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
|
||||
0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
|
||||
0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
|
||||
0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
|
||||
0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
|
||||
0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
|
||||
0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
|
||||
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
|
||||
0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
|
||||
0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
|
||||
0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
|
||||
0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
|
||||
0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
|
||||
0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
|
||||
0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
|
||||
0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
|
||||
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
|
||||
0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
|
||||
0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
|
||||
0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
|
||||
0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
|
||||
0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
|
||||
0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
|
||||
0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
|
||||
0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
|
||||
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
|
||||
0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
|
||||
0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
|
||||
0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
|
||||
0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
|
||||
0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
|
||||
0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
|
||||
0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
|
||||
0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
|
||||
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
|
||||
0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
|
||||
0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
|
||||
0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
|
||||
0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
|
||||
0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
|
||||
0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
|
||||
0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
|
||||
0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
|
||||
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
|
||||
0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
|
||||
0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
|
||||
0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
|
||||
0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
|
||||
0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
|
||||
0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
|
||||
0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
|
||||
0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
|
||||
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
|
||||
0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
|
||||
0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
|
||||
0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
|
||||
0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
|
||||
0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
|
||||
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
|
||||
0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
|
||||
0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
|
||||
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0,],
|
||||
[0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
|
||||
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
|
||||
0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
|
||||
0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
|
||||
0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
|
||||
0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
|
||||
0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
|
||||
0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
|
||||
0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
|
||||
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
|
||||
0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
|
||||
0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
|
||||
0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
|
||||
0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
|
||||
0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
|
||||
0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
|
||||
0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
|
||||
0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
|
||||
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
|
||||
0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
|
||||
0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
|
||||
0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
|
||||
0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
|
||||
0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
|
||||
0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
|
||||
0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
|
||||
0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
|
||||
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
|
||||
0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
|
||||
0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
|
||||
0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
|
||||
0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
|
||||
0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
|
||||
0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
|
||||
0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
|
||||
0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
|
||||
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
|
||||
0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
|
||||
0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
|
||||
0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
|
||||
0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
|
||||
0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
|
||||
0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
|
||||
0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
|
||||
0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
|
||||
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
|
||||
0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
|
||||
0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
|
||||
0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
|
||||
0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
|
||||
0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
|
||||
0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
|
||||
0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
|
||||
0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
|
||||
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
|
||||
0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
|
||||
0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
|
||||
0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
|
||||
0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
|
||||
0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
|
||||
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
|
||||
0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
|
||||
0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
|
||||
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6,],
|
||||
];
|
||||
|
||||
const blowfishCtx = {
|
||||
pbox: [],
|
||||
sbox: [],
|
||||
};
|
||||
|
||||
function f(ctx, x) {
|
||||
const a = (x >> 24) & 0xFF;
|
||||
const b = (x >> 16) & 0xFF;
|
||||
const c = (x >> 8) & 0xFF;
|
||||
const d = x & 0xFF;
|
||||
|
||||
let y = ctx.sbox[0][a] + ctx.sbox[1][b];
|
||||
y = y ^ ctx.sbox[2][c];
|
||||
y = y + ctx.sbox[3][d];
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
function blowfishEncrypt(ctx, left, right) {
|
||||
let Xl = left;
|
||||
let Xr = right;
|
||||
let temp;
|
||||
|
||||
for(let i = 0; i < N; ++i){
|
||||
Xl = Xl ^ ctx.pbox[i];
|
||||
Xr = f(ctx, Xl) ^ Xr;
|
||||
|
||||
temp = Xl;
|
||||
Xl = Xr;
|
||||
Xr = temp;
|
||||
}
|
||||
|
||||
temp = Xl;
|
||||
Xl = Xr;
|
||||
Xr = temp;
|
||||
|
||||
Xr = Xr ^ ctx.pbox[N];
|
||||
Xl = Xl ^ ctx.pbox[N + 1];
|
||||
|
||||
return {left: Xl, right: Xr};
|
||||
}
|
||||
|
||||
function blowfishDecrypt(ctx, left, right) {
|
||||
let Xl = left;
|
||||
let Xr = right;
|
||||
let temp;
|
||||
|
||||
for(let i = N + 1; i > 1; --i){
|
||||
Xl = Xl ^ ctx.pbox[i];
|
||||
Xr = f(ctx, Xl) ^ Xr;
|
||||
|
||||
temp = Xl;
|
||||
Xl = Xr;
|
||||
Xr = temp;
|
||||
}
|
||||
|
||||
temp = Xl;
|
||||
Xl = Xr;
|
||||
Xr = temp;
|
||||
|
||||
Xr = Xr ^ ctx.pbox[1];
|
||||
Xl = Xl ^ ctx.pbox[0];
|
||||
|
||||
return {left: Xl, right: Xr};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization ctx's pbox and sbox.
|
||||
*
|
||||
* @param {Object} ctx The object has pbox and sbox.
|
||||
* @param {Array} key An array of 32-bit words.
|
||||
* @param {int} keysize The length of the key.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* blowfishInit(BLOWFISH_CTX, key, 128/32);
|
||||
*/
|
||||
function blowfishInit(ctx, key, keysize) {
|
||||
for (let Row = 0; Row < 4; Row++) {
|
||||
ctx.sbox[Row] = [];
|
||||
for (let Col = 0; Col < 256; Col++) {
|
||||
ctx.sbox[Row][Col] = ORIG_S[Row][Col];
|
||||
}
|
||||
}
|
||||
|
||||
let keyIndex = 0;
|
||||
for (let index = 0; index < N + 2; index++) {
|
||||
ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex];
|
||||
keyIndex++;
|
||||
if (keyIndex >= keysize) {
|
||||
keyIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let data1 = 0;
|
||||
let data2 = 0;
|
||||
let res = 0;
|
||||
for (let i = 0; i < N + 2; i += 2) {
|
||||
res = blowfishEncrypt(ctx, data1, data2);
|
||||
data1 = res.left;
|
||||
data2 = res.right;
|
||||
ctx.pbox[i] = data1;
|
||||
ctx.pbox[i + 1] = data2;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
for (let j = 0; j < 256; j += 2) {
|
||||
res = blowfishEncrypt(ctx, data1, data2);
|
||||
data1 = res.left;
|
||||
data2 = res.right;
|
||||
ctx.sbox[i][j] = data1;
|
||||
ctx.sbox[i][j + 1] = data2;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blowfish block cipher algorithm.
|
||||
*/
|
||||
export class BlowfishAlgo extends BlockCipher {
|
||||
constructor(xformMode, key, cfg) {
|
||||
super(xformMode, key, cfg);
|
||||
|
||||
// blickSize is an instance field and should set in constructor.
|
||||
this.blockSize = 64 / 32;
|
||||
}
|
||||
|
||||
_doReset() {
|
||||
// Skip reset of nRounds has been set before and key did not change
|
||||
if (this._keyPriorReset === this._key) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
const key = this._keyPriorReset = this._key;
|
||||
const keyWords = key.words;
|
||||
const keySize = key.sigBytes / 4;
|
||||
|
||||
//Initialization pbox and sbox
|
||||
blowfishInit(blowfishCtx, keyWords, keySize);
|
||||
}
|
||||
|
||||
encryptBlock(M, offset) {
|
||||
const res = blowfishEncrypt(blowfishCtx, M[offset], M[offset + 1]);
|
||||
M[offset] = res.left;
|
||||
M[offset + 1] = res.right;
|
||||
}
|
||||
|
||||
decryptBlock(M, offset) {
|
||||
const res = blowfishDecrypt(blowfishCtx, M[offset], M[offset + 1]);
|
||||
M[offset] = res.left;
|
||||
M[offset + 1] = res.right;
|
||||
}
|
||||
}
|
||||
BlowfishAlgo.keySize = 128 / 32;
|
||||
BlowfishAlgo.ivSize = 64 / 32;
|
||||
// blickSize is an instance field and should set in constructor.
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const Blowfish = BlockCipher._createHelper(BlowfishAlgo);
|
||||
@@ -0,0 +1,442 @@
|
||||
export interface CipherCfg {
|
||||
// Cipher
|
||||
iv?: WordArray;
|
||||
mode?: Function;
|
||||
padding?: Padding;
|
||||
// SerializableCipher
|
||||
format?: Format;
|
||||
// PasswordBasedCipher
|
||||
kdf?: Kdf;
|
||||
salt?: WordArray | string;
|
||||
hasher?: Function;
|
||||
// RC4Drop
|
||||
drop?: number;
|
||||
}
|
||||
export interface CipherObj {
|
||||
encrypt(message: WordArray | string, key: WordArray | string, cfg?: CipherCfg): CipherParams;
|
||||
decrypt(ciphertext: CipherParams | CipherParamsCfg | string, key: WordArray | string, cfg?: CipherCfg): WordArray;
|
||||
}
|
||||
/**
|
||||
* Abstract base cipher template.
|
||||
*
|
||||
* @property {number} keySize This cipher's key size. Default: 4 (128 bits)
|
||||
* @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
|
||||
* @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
|
||||
* @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
|
||||
*/
|
||||
export class Cipher extends BufferedBlockAlgorithm {
|
||||
static keySize: number;
|
||||
static ivSize: number;
|
||||
static _ENC_XFORM_MODE: number;
|
||||
static _DEC_XFORM_MODE: number;
|
||||
blockSize: number;
|
||||
/**
|
||||
* Creates this cipher in encryption mode.
|
||||
*
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {Cipher} A cipher instance.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
|
||||
*/
|
||||
static createEncryptor(key: WordArray, cfg?: CipherCfg): Cipher;
|
||||
/**
|
||||
* Creates this cipher in decryption mode.
|
||||
*
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {Cipher} A cipher instance.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
|
||||
*/
|
||||
static createDecryptor(key: WordArray, cfg?: CipherCfg): Cipher;
|
||||
/**
|
||||
* Creates shortcut functions to a cipher's object interface.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher to create a helper for.
|
||||
*
|
||||
* @return {Object} An object with encrypt and decrypt shortcut functions.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
|
||||
*/
|
||||
static _createHelper(SubCipher: Function): CipherObj;
|
||||
/**
|
||||
* Initializes a newly created cipher.
|
||||
*
|
||||
* @param {number} xformMode Either the encryption or decryption transormation mode constant.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const cipher = CryptoJS.algo.AES.create(
|
||||
* CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }
|
||||
* );
|
||||
*/
|
||||
static create(xformMode: number, key: WordArray, cfg?: CipherCfg): Cipher;
|
||||
constructor(xformMode: number, key: WordArray, cfg?: CipherCfg);
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {WordArray} iv The IV to use for this operation.
|
||||
*/
|
||||
cfg: Base & CipherCfg;
|
||||
_xformMode: number;
|
||||
_key: WordArray;
|
||||
/**
|
||||
* Adds data to be encrypted or decrypted.
|
||||
*
|
||||
* @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
|
||||
*
|
||||
* @return {WordArray} The data after processing.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const encrypted = cipher.process('data');
|
||||
* const encrypted = cipher.process(wordArray);
|
||||
*/
|
||||
process(dataUpdate: WordArray | string): WordArray;
|
||||
/**
|
||||
* Finalizes the encryption or decryption process.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
|
||||
*
|
||||
* @return {WordArray} The data after final processing.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const encrypted = cipher.finalize();
|
||||
* const encrypted = cipher.finalize('data');
|
||||
* const encrypted = cipher.finalize(wordArray);
|
||||
*/
|
||||
finalize(dataUpdate?: WordArray | string): WordArray;
|
||||
}
|
||||
/**
|
||||
* Abstract base stream cipher template.
|
||||
*
|
||||
* @property {number} blockSize
|
||||
*
|
||||
* The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
|
||||
*/
|
||||
export class StreamCipher extends Cipher {
|
||||
static create(...args: Array<any>): StreamCipher;
|
||||
constructor(...args: Array<any>);
|
||||
_doFinalize(): WordArray;
|
||||
}
|
||||
/**
|
||||
* Abstract base block cipher mode template.
|
||||
*/
|
||||
export class BlockCipherMode extends Base {
|
||||
static Encryptor: BlockCipherMode;
|
||||
static Decryptor: BlockCipherMode;
|
||||
/**
|
||||
* Creates this mode for encryption.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
|
||||
*/
|
||||
static createEncryptor(cipher: Cipher, iv: number[]): BlockCipherMode;
|
||||
/**
|
||||
* Creates this mode for decryption.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
|
||||
*/
|
||||
static createDecryptor(cipher: Cipher, iv: number[]): BlockCipherMode;
|
||||
/**
|
||||
* Initializes a newly created mode.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
|
||||
*/
|
||||
static create(cipher: Cipher, iv: Array<number>): BlockCipherMode;
|
||||
constructor(cipher: Cipher, iv: Array<number>);
|
||||
_cipher: Cipher;
|
||||
_iv: number[];
|
||||
/**
|
||||
* Processes the data block at offset.
|
||||
*
|
||||
* @param {Array} words The data words to operate on.
|
||||
* @param {number} offset The offset where the block starts.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* mode.processBlock(data.words, offset);
|
||||
*/
|
||||
processBlock(words: number[], offset: number): void;
|
||||
}
|
||||
/**
|
||||
* Cipher Block Chaining mode.
|
||||
*/
|
||||
/**
|
||||
* Abstract base CBC mode.
|
||||
*/
|
||||
export class CBC extends BlockCipherMode {
|
||||
}
|
||||
export interface Padding {
|
||||
pad(data: WordArray, blockSize: number): void;
|
||||
unpad(data: WordArray): void;
|
||||
}
|
||||
/**
|
||||
* PKCS #5/7 padding strategy.
|
||||
*/
|
||||
export const Pkcs7: Padding;
|
||||
/**
|
||||
* Abstract base block cipher template.
|
||||
*
|
||||
* @property {number} blockSize
|
||||
*
|
||||
* The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
|
||||
*/
|
||||
export class BlockCipher extends Cipher {
|
||||
static create(xformMode: number, key: WordArray, cfg?: CipherCfg): BlockCipher;
|
||||
constructor(xformMode: number, key: WordArray, cfg?: CipherCfg);
|
||||
_mode: BlockCipherMode;
|
||||
_doProcessBlock(words: number[], offset: number): void;
|
||||
_doFinalize(): WordArray;
|
||||
encryptBlock(M: number[], offset: number): void;
|
||||
decryptBlock(M: number[], offset: number): void;
|
||||
}
|
||||
export interface CipherParamsCfg {
|
||||
ciphertext?: WordArray;
|
||||
key?: WordArray;
|
||||
iv?: WordArray;
|
||||
salt?: WordArray;
|
||||
algorithm?: Function;
|
||||
mode?: Function;
|
||||
padding?: Padding;
|
||||
blockSize?: number;
|
||||
formatter?: Format;
|
||||
}
|
||||
/**
|
||||
* A collection of cipher parameters.
|
||||
*
|
||||
* @property {WordArray} ciphertext The raw ciphertext.
|
||||
* @property {WordArray} key The key to this ciphertext.
|
||||
* @property {WordArray} iv The IV used in the ciphering operation.
|
||||
* @property {WordArray} salt The salt used with a key derivation function.
|
||||
* @property {Cipher} algorithm The cipher algorithm.
|
||||
* @property {Mode} mode The block mode used in the ciphering operation.
|
||||
* @property {Padding} padding The padding scheme used in the ciphering operation.
|
||||
* @property {number} blockSize The block size of the cipher.
|
||||
* @property {Format} formatter
|
||||
* The default formatting strategy to convert this cipher params object to a string.
|
||||
*/
|
||||
export class CipherParams extends Base {
|
||||
ciphertext?: WordArray;
|
||||
key?: WordArray;
|
||||
iv?: WordArray;
|
||||
salt?: WordArray;
|
||||
algorithm?: Function;
|
||||
mode?: Function;
|
||||
padding?: Padding;
|
||||
blockSize?: number;
|
||||
formatter?: Format;
|
||||
/**
|
||||
* Initializes a newly created cipher params object.
|
||||
*
|
||||
* @param {Object} cipherParams An object with any of the possible cipher parameters.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
* ciphertext: ciphertextWordArray,
|
||||
* key: keyWordArray,
|
||||
* iv: ivWordArray,
|
||||
* salt: saltWordArray,
|
||||
* algorithm: CryptoJS.algo.AES,
|
||||
* mode: CryptoJS.mode.CBC,
|
||||
* padding: CryptoJS.pad.PKCS7,
|
||||
* blockSize: 4,
|
||||
* formatter: CryptoJS.format.OpenSSL
|
||||
* });
|
||||
*/
|
||||
static create(cipherParams: CipherParams | CipherParamsCfg): CipherParams;
|
||||
constructor(cipherParams: CipherParams | CipherParamsCfg);
|
||||
/**
|
||||
* Converts this cipher params object to a string.
|
||||
*
|
||||
* @param {Format} formatter (Optional) The formatting strategy to use.
|
||||
*
|
||||
* @return {string} The stringified cipher params.
|
||||
*
|
||||
* @throws Error If neither the formatter nor the default formatter is set.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var string = cipherParams + '';
|
||||
* var string = cipherParams.toString();
|
||||
* var string = cipherParams.toString(CryptoJS.format.OpenSSL);
|
||||
*/
|
||||
toString(formatter?: Format): string;
|
||||
}
|
||||
export interface Format {
|
||||
stringify(cipherParams: CipherParams): string;
|
||||
parse(str: string): CipherParams;
|
||||
}
|
||||
/**
|
||||
* OpenSSL formatting strategy.
|
||||
*/
|
||||
export const OpenSSLFormatter: Format;
|
||||
/**
|
||||
* A cipher wrapper that returns ciphertext as a serializable cipher params object.
|
||||
*/
|
||||
export class SerializableCipher extends Base {
|
||||
static cfg: Base & {
|
||||
format: Format;
|
||||
};
|
||||
/**
|
||||
* Encrypts a message.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {WordArray|string} message The message to encrypt.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {CipherParams} A cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, key);
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
static encrypt(cipher: Function, message: WordArray | string, key: WordArray | string, cfg?: CipherCfg): CipherParams;
|
||||
/**
|
||||
* Decrypts serialized ciphertext.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {WordArray} The plaintext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var plaintext = CryptoJS.lib.SerializableCipher
|
||||
* .decrypt(CryptoJS.algo.AES, formattedCiphertext, key,
|
||||
* { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
* var plaintext = CryptoJS.lib.SerializableCipher
|
||||
* .decrypt(CryptoJS.algo.AES, ciphertextParams, key,
|
||||
* { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
static decrypt(cipher: Function, ciphertext: CipherParams | string, key: WordArray | string, cfg?: CipherCfg): WordArray;
|
||||
/**
|
||||
* Converts serialized ciphertext to CipherParams,
|
||||
* else assumed CipherParams already and returns ciphertext unchanged.
|
||||
*
|
||||
* @param {CipherParams|string} ciphertext The ciphertext.
|
||||
* @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
|
||||
*
|
||||
* @return {CipherParams} The unserialized ciphertext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher
|
||||
* ._parse(ciphertextStringOrParams, format);
|
||||
*/
|
||||
static _parse(ciphertext: CipherParams | string, format: Format): CipherParams;
|
||||
}
|
||||
export interface Kdf {
|
||||
execute(password: string, keySize: number, ivSize: number, salt?: WordArray | string, hasher?: Function): CipherParams;
|
||||
}
|
||||
/**
|
||||
* OpenSSL key derivation function.
|
||||
*/
|
||||
export const OpenSSLKdf: Kdf;
|
||||
/**
|
||||
* A serializable cipher wrapper that derives the key from a password,
|
||||
* and returns ciphertext as a serializable cipher params object.
|
||||
*/
|
||||
export class PasswordBasedCipher extends SerializableCipher {
|
||||
static cfg: Base & {
|
||||
format: Format;
|
||||
kdf: Kdf;
|
||||
};
|
||||
/**
|
||||
* Encrypts a message using a password.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {WordArray|string} message The message to encrypt.
|
||||
* @param {string} password The password.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {CipherParams} A cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, 'password');
|
||||
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
static encrypt(cipher: Function, message: WordArray | string, passed: string, cfg?: CipherCfg): CipherParams;
|
||||
/**
|
||||
* Decrypts serialized ciphertext using a password.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
|
||||
* @param {string} password The password.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {WordArray} The plaintext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var plaintext = CryptoJS.lib.PasswordBasedCipher
|
||||
* .decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password',
|
||||
* { format: CryptoJS.format.OpenSSL });
|
||||
* var plaintext = CryptoJS.lib.PasswordBasedCipher
|
||||
* .decrypt(CryptoJS.algo.AES, ciphertextParams, 'password',
|
||||
* { format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
static decrypt(cipher: Function, ciphertext: CipherParams | string, password: string, cfg?: CipherCfg): WordArray;
|
||||
}
|
||||
import { BufferedBlockAlgorithm } from './core.js';
|
||||
import { WordArray } from './core.js';
|
||||
import { Base } from './core.js';
|
||||
@@ -0,0 +1,883 @@
|
||||
/* eslint-disable no-use-before-define */
|
||||
|
||||
import {
|
||||
Base,
|
||||
WordArray,
|
||||
BufferedBlockAlgorithm,
|
||||
} from './core.js';
|
||||
import { Base64 } from './enc-base64.js';
|
||||
import { EvpKDFAlgo } from './evpkdf.js';
|
||||
|
||||
/**
|
||||
* Abstract base cipher template.
|
||||
*
|
||||
* @property {number} keySize This cipher's key size. Default: 4 (128 bits)
|
||||
* @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
|
||||
* @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
|
||||
* @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
|
||||
*/
|
||||
export class Cipher extends BufferedBlockAlgorithm {
|
||||
/**
|
||||
* Initializes a newly created cipher.
|
||||
*
|
||||
* @param {number} xformMode Either the encryption or decryption transormation mode constant.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const cipher = CryptoJS.algo.AES.create(
|
||||
* CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }
|
||||
* );
|
||||
*/
|
||||
constructor(xformMode, key, cfg) {
|
||||
super();
|
||||
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {WordArray} iv The IV to use for this operation.
|
||||
*/
|
||||
this.cfg = Object.assign(new Base(), cfg);
|
||||
|
||||
// Store transform mode and key
|
||||
this._xformMode = xformMode;
|
||||
this._key = key;
|
||||
|
||||
// Set initial values
|
||||
this.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this cipher in encryption mode.
|
||||
*
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {Cipher} A cipher instance.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
|
||||
*/
|
||||
static createEncryptor(key, cfg) {
|
||||
return this.create(this._ENC_XFORM_MODE, key, cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this cipher in decryption mode.
|
||||
*
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {Cipher} A cipher instance.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
|
||||
*/
|
||||
static createDecryptor(key, cfg) {
|
||||
return this.create(this._DEC_XFORM_MODE, key, cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates shortcut functions to a cipher's object interface.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher to create a helper for.
|
||||
*
|
||||
* @return {Object} An object with encrypt and decrypt shortcut functions.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
|
||||
*/
|
||||
static _createHelper(SubCipher) {
|
||||
const selectCipherStrategy = (key) => {
|
||||
if (typeof key === 'string') {
|
||||
return PasswordBasedCipher;
|
||||
}
|
||||
return SerializableCipher;
|
||||
};
|
||||
|
||||
return {
|
||||
encrypt(message, key, cfg) {
|
||||
return selectCipherStrategy(key).encrypt(SubCipher, message, key, cfg);
|
||||
},
|
||||
|
||||
decrypt(ciphertext, key, cfg) {
|
||||
return selectCipherStrategy(key).decrypt(SubCipher, ciphertext, key, cfg);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this cipher to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* cipher.reset();
|
||||
*/
|
||||
reset() {
|
||||
// Reset data buffer
|
||||
super.reset.call(this);
|
||||
|
||||
// Perform concrete-cipher logic
|
||||
this._doReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds data to be encrypted or decrypted.
|
||||
*
|
||||
* @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
|
||||
*
|
||||
* @return {WordArray} The data after processing.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const encrypted = cipher.process('data');
|
||||
* const encrypted = cipher.process(wordArray);
|
||||
*/
|
||||
process(dataUpdate) {
|
||||
// Append
|
||||
this._append(dataUpdate);
|
||||
|
||||
// Process available blocks
|
||||
return this._process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the encryption or decryption process.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
|
||||
*
|
||||
* @return {WordArray} The data after final processing.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const encrypted = cipher.finalize();
|
||||
* const encrypted = cipher.finalize('data');
|
||||
* const encrypted = cipher.finalize(wordArray);
|
||||
*/
|
||||
finalize(dataUpdate) {
|
||||
// Final data update
|
||||
if (dataUpdate) {
|
||||
this._append(dataUpdate);
|
||||
}
|
||||
|
||||
// Perform concrete-cipher logic
|
||||
const finalProcessedData = this._doFinalize();
|
||||
|
||||
return finalProcessedData;
|
||||
}
|
||||
}
|
||||
Cipher._ENC_XFORM_MODE = 1;
|
||||
Cipher._DEC_XFORM_MODE = 2;
|
||||
Cipher.keySize = 128 / 32;
|
||||
Cipher.ivSize = 128 / 32;
|
||||
|
||||
/**
|
||||
* Abstract base stream cipher template.
|
||||
*
|
||||
* @property {number} blockSize
|
||||
*
|
||||
* The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
|
||||
*/
|
||||
export class StreamCipher extends Cipher {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
this.blockSize = 1;
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
// Process partial blocks
|
||||
const finalProcessedBlocks = this._process(!!'flush');
|
||||
|
||||
return finalProcessedBlocks;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base block cipher mode template.
|
||||
*/
|
||||
export class BlockCipherMode extends Base {
|
||||
/**
|
||||
* Initializes a newly created mode.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
|
||||
*/
|
||||
constructor(cipher, iv) {
|
||||
super();
|
||||
|
||||
this._cipher = cipher;
|
||||
this._iv = iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this mode for encryption.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
|
||||
*/
|
||||
static createEncryptor(cipher, iv) {
|
||||
return this.Encryptor.create(cipher, iv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this mode for decryption.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
|
||||
*/
|
||||
static createDecryptor(cipher, iv) {
|
||||
return this.Decryptor.create(cipher, iv);
|
||||
}
|
||||
}
|
||||
|
||||
function xorBlock(words, offset, blockSize) {
|
||||
const _words = words;
|
||||
let block;
|
||||
|
||||
// Shortcut
|
||||
const iv = this._iv;
|
||||
|
||||
// Choose mixing block
|
||||
if (iv) {
|
||||
block = iv;
|
||||
|
||||
// Remove IV for subsequent blocks
|
||||
this._iv = undefined;
|
||||
} else {
|
||||
block = this._prevBlock;
|
||||
}
|
||||
|
||||
// XOR blocks
|
||||
for (let i = 0; i < blockSize; i += 1) {
|
||||
_words[offset + i] ^= block[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cipher Block Chaining mode.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract base CBC mode.
|
||||
*/
|
||||
export class CBC extends BlockCipherMode {
|
||||
}
|
||||
/**
|
||||
* CBC encryptor.
|
||||
*/
|
||||
CBC.Encryptor = class extends CBC {
|
||||
/**
|
||||
* Processes the data block at offset.
|
||||
*
|
||||
* @param {Array} words The data words to operate on.
|
||||
* @param {number} offset The offset where the block starts.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* mode.processBlock(data.words, offset);
|
||||
*/
|
||||
processBlock(words, offset) {
|
||||
// Shortcuts
|
||||
const cipher = this._cipher;
|
||||
const { blockSize } = cipher;
|
||||
|
||||
// XOR and encrypt
|
||||
xorBlock.call(this, words, offset, blockSize);
|
||||
cipher.encryptBlock(words, offset);
|
||||
|
||||
// Remember this block to use with next block
|
||||
this._prevBlock = words.slice(offset, offset + blockSize);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* CBC decryptor.
|
||||
*/
|
||||
CBC.Decryptor = class extends CBC {
|
||||
/**
|
||||
* Processes the data block at offset.
|
||||
*
|
||||
* @param {Array} words The data words to operate on.
|
||||
* @param {number} offset The offset where the block starts.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* mode.processBlock(data.words, offset);
|
||||
*/
|
||||
processBlock(words, offset) {
|
||||
// Shortcuts
|
||||
const cipher = this._cipher;
|
||||
const { blockSize } = cipher;
|
||||
|
||||
// Remember this block to use with next block
|
||||
const thisBlock = words.slice(offset, offset + blockSize);
|
||||
|
||||
// Decrypt and XOR
|
||||
cipher.decryptBlock(words, offset);
|
||||
xorBlock.call(this, words, offset, blockSize);
|
||||
|
||||
// This block becomes the previous block
|
||||
this._prevBlock = thisBlock;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* PKCS #5/7 padding strategy.
|
||||
*/
|
||||
export const Pkcs7 = {
|
||||
/**
|
||||
* Pads data using the algorithm defined in PKCS #5/7.
|
||||
*
|
||||
* @param {WordArray} data The data to pad.
|
||||
* @param {number} blockSize The multiple that the data should be padded to.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* CryptoJS.pad.Pkcs7.pad(wordArray, 4);
|
||||
*/
|
||||
pad(data, blockSize) {
|
||||
// Shortcut
|
||||
const blockSizeBytes = blockSize * 4;
|
||||
|
||||
// Count padding bytes
|
||||
const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes);
|
||||
|
||||
// Create padding word
|
||||
const paddingWord = (nPaddingBytes << 24)
|
||||
| (nPaddingBytes << 16)
|
||||
| (nPaddingBytes << 8)
|
||||
| nPaddingBytes;
|
||||
|
||||
// Create padding
|
||||
const paddingWords = [];
|
||||
for (let i = 0; i < nPaddingBytes; i += 4) {
|
||||
paddingWords.push(paddingWord);
|
||||
}
|
||||
const padding = WordArray.create(paddingWords, nPaddingBytes);
|
||||
|
||||
// Add padding
|
||||
data.concat(padding);
|
||||
},
|
||||
|
||||
/**
|
||||
* Unpads data that had been padded using the algorithm defined in PKCS #5/7.
|
||||
*
|
||||
* @param {WordArray} data The data to unpad.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* CryptoJS.pad.Pkcs7.unpad(wordArray);
|
||||
*/
|
||||
unpad(data) {
|
||||
const _data = data;
|
||||
|
||||
// Get number of padding bytes from last byte
|
||||
const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff;
|
||||
|
||||
// Remove padding
|
||||
_data.sigBytes -= nPaddingBytes;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract base block cipher template.
|
||||
*
|
||||
* @property {number} blockSize
|
||||
*
|
||||
* The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
|
||||
*/
|
||||
export class BlockCipher extends Cipher {
|
||||
constructor(xformMode, key, cfg) {
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {Mode} mode The block mode to use. Default: CBC
|
||||
* @property {Padding} padding The padding strategy to use. Default: Pkcs7
|
||||
*/
|
||||
super(xformMode, key, Object.assign(
|
||||
{
|
||||
mode: CBC,
|
||||
padding: Pkcs7,
|
||||
},
|
||||
cfg,
|
||||
));
|
||||
|
||||
this.blockSize = 128 / 32;
|
||||
}
|
||||
|
||||
reset() {
|
||||
let modeCreator;
|
||||
|
||||
// Reset cipher
|
||||
super.reset.call(this);
|
||||
|
||||
// Shortcuts
|
||||
const { cfg } = this;
|
||||
const { iv, mode } = cfg;
|
||||
|
||||
// Reset block mode
|
||||
if (this._xformMode === this.constructor._ENC_XFORM_MODE) {
|
||||
modeCreator = mode.createEncryptor;
|
||||
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
|
||||
modeCreator = mode.createDecryptor;
|
||||
// Keep at least one block in the buffer for unpadding
|
||||
this._minBufferSize = 1;
|
||||
}
|
||||
|
||||
this._mode = modeCreator.call(mode, this, iv && iv.words);
|
||||
this._mode.__creator = modeCreator;
|
||||
}
|
||||
|
||||
_doProcessBlock(words, offset) {
|
||||
this._mode.processBlock(words, offset);
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
let finalProcessedBlocks;
|
||||
|
||||
// Shortcut
|
||||
const { padding } = this.cfg;
|
||||
|
||||
// Finalize
|
||||
if (this._xformMode === this.constructor._ENC_XFORM_MODE) {
|
||||
// Pad data
|
||||
padding.pad(this._data, this.blockSize);
|
||||
|
||||
// Process final blocks
|
||||
finalProcessedBlocks = this._process(!!'flush');
|
||||
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
|
||||
// Process final blocks
|
||||
finalProcessedBlocks = this._process(!!'flush');
|
||||
|
||||
// Unpad data
|
||||
padding.unpad(finalProcessedBlocks);
|
||||
}
|
||||
|
||||
return finalProcessedBlocks;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of cipher parameters.
|
||||
*
|
||||
* @property {WordArray} ciphertext The raw ciphertext.
|
||||
* @property {WordArray} key The key to this ciphertext.
|
||||
* @property {WordArray} iv The IV used in the ciphering operation.
|
||||
* @property {WordArray} salt The salt used with a key derivation function.
|
||||
* @property {Cipher} algorithm The cipher algorithm.
|
||||
* @property {Mode} mode The block mode used in the ciphering operation.
|
||||
* @property {Padding} padding The padding scheme used in the ciphering operation.
|
||||
* @property {number} blockSize The block size of the cipher.
|
||||
* @property {Format} formatter
|
||||
* The default formatting strategy to convert this cipher params object to a string.
|
||||
*/
|
||||
export class CipherParams extends Base {
|
||||
/**
|
||||
* Initializes a newly created cipher params object.
|
||||
*
|
||||
* @param {Object} cipherParams An object with any of the possible cipher parameters.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
* ciphertext: ciphertextWordArray,
|
||||
* key: keyWordArray,
|
||||
* iv: ivWordArray,
|
||||
* salt: saltWordArray,
|
||||
* algorithm: CryptoJS.algo.AES,
|
||||
* mode: CryptoJS.mode.CBC,
|
||||
* padding: CryptoJS.pad.PKCS7,
|
||||
* blockSize: 4,
|
||||
* formatter: CryptoJS.format.OpenSSL
|
||||
* });
|
||||
*/
|
||||
constructor(cipherParams) {
|
||||
super();
|
||||
|
||||
this.mixIn(cipherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this cipher params object to a string.
|
||||
*
|
||||
* @param {Format} formatter (Optional) The formatting strategy to use.
|
||||
*
|
||||
* @return {string} The stringified cipher params.
|
||||
*
|
||||
* @throws Error If neither the formatter nor the default formatter is set.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var string = cipherParams + '';
|
||||
* var string = cipherParams.toString();
|
||||
* var string = cipherParams.toString(CryptoJS.format.OpenSSL);
|
||||
*/
|
||||
toString(formatter) {
|
||||
return (formatter || this.formatter).stringify(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenSSL formatting strategy.
|
||||
*/
|
||||
export const OpenSSLFormatter = {
|
||||
/**
|
||||
* Converts a cipher params object to an OpenSSL-compatible string.
|
||||
*
|
||||
* @param {CipherParams} cipherParams The cipher params object.
|
||||
*
|
||||
* @return {string} The OpenSSL-compatible string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
|
||||
*/
|
||||
stringify(cipherParams) {
|
||||
let wordArray;
|
||||
|
||||
// Shortcuts
|
||||
const { ciphertext, salt } = cipherParams;
|
||||
|
||||
// Format
|
||||
if (salt) {
|
||||
wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
|
||||
} else {
|
||||
wordArray = ciphertext;
|
||||
}
|
||||
|
||||
return wordArray.toString(Base64);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts an OpenSSL-compatible string to a cipher params object.
|
||||
*
|
||||
* @param {string} openSSLStr The OpenSSL-compatible string.
|
||||
*
|
||||
* @return {CipherParams} The cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
|
||||
*/
|
||||
parse(openSSLStr) {
|
||||
let salt;
|
||||
|
||||
// Parse base64
|
||||
const ciphertext = Base64.parse(openSSLStr);
|
||||
|
||||
// Shortcut
|
||||
const ciphertextWords = ciphertext.words;
|
||||
|
||||
// Test for salt
|
||||
if (ciphertextWords[0] === 0x53616c74 && ciphertextWords[1] === 0x65645f5f) {
|
||||
// Extract salt
|
||||
salt = WordArray.create(ciphertextWords.slice(2, 4));
|
||||
|
||||
// Remove salt from ciphertext
|
||||
ciphertextWords.splice(0, 4);
|
||||
ciphertext.sigBytes -= 16;
|
||||
}
|
||||
|
||||
return CipherParams.create({ ciphertext, salt });
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A cipher wrapper that returns ciphertext as a serializable cipher params object.
|
||||
*/
|
||||
export class SerializableCipher extends Base {
|
||||
/**
|
||||
* Encrypts a message.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {WordArray|string} message The message to encrypt.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {CipherParams} A cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, key);
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
static encrypt(cipher, message, key, cfg) {
|
||||
// Apply config defaults
|
||||
const _cfg = Object.assign(new Base(), this.cfg, cfg);
|
||||
|
||||
// Encrypt
|
||||
const encryptor = cipher.createEncryptor(key, _cfg);
|
||||
const ciphertext = encryptor.finalize(message);
|
||||
|
||||
// Shortcut
|
||||
const cipherCfg = encryptor.cfg;
|
||||
|
||||
// Create and return serializable cipher params
|
||||
return CipherParams.create({
|
||||
ciphertext,
|
||||
key,
|
||||
iv: cipherCfg.iv,
|
||||
algorithm: cipher,
|
||||
mode: cipherCfg.mode,
|
||||
padding: cipherCfg.padding,
|
||||
blockSize: encryptor.blockSize,
|
||||
formatter: _cfg.format,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts serialized ciphertext.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {WordArray} The plaintext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var plaintext = CryptoJS.lib.SerializableCipher
|
||||
* .decrypt(CryptoJS.algo.AES, formattedCiphertext, key,
|
||||
* { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
* var plaintext = CryptoJS.lib.SerializableCipher
|
||||
* .decrypt(CryptoJS.algo.AES, ciphertextParams, key,
|
||||
* { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
static decrypt(cipher, ciphertext, key, cfg) {
|
||||
let _ciphertext = ciphertext;
|
||||
|
||||
// Apply config defaults
|
||||
const _cfg = Object.assign(new Base(), this.cfg, cfg);
|
||||
|
||||
// Convert string to CipherParams
|
||||
_ciphertext = this._parse(_ciphertext, _cfg.format);
|
||||
|
||||
// Decrypt
|
||||
const plaintext = cipher.createDecryptor(key, _cfg).finalize(_ciphertext.ciphertext);
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts serialized ciphertext to CipherParams,
|
||||
* else assumed CipherParams already and returns ciphertext unchanged.
|
||||
*
|
||||
* @param {CipherParams|string} ciphertext The ciphertext.
|
||||
* @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
|
||||
*
|
||||
* @return {CipherParams} The unserialized ciphertext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher
|
||||
* ._parse(ciphertextStringOrParams, format);
|
||||
*/
|
||||
static _parse(ciphertext, format) {
|
||||
if (typeof ciphertext === 'string') {
|
||||
return format.parse(ciphertext, this);
|
||||
}
|
||||
return ciphertext;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {Formatter} format
|
||||
*
|
||||
* The formatting strategy to convert cipher param objects to and from a string.
|
||||
* Default: OpenSSL
|
||||
*/
|
||||
SerializableCipher.cfg = Object.assign(
|
||||
new Base(),
|
||||
{ format: OpenSSLFormatter },
|
||||
);
|
||||
|
||||
/**
|
||||
* OpenSSL key derivation function.
|
||||
*/
|
||||
export const OpenSSLKdf = {
|
||||
/**
|
||||
* Derives a key and IV from a password.
|
||||
*
|
||||
* @param {string} password The password to derive from.
|
||||
* @param {number} keySize The size in words of the key to generate.
|
||||
* @param {number} ivSize The size in words of the IV to generate.
|
||||
* @param {WordArray|string} salt
|
||||
* (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
|
||||
*
|
||||
* @return {CipherParams} A cipher params object with the key, IV, and salt.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
|
||||
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
|
||||
*/
|
||||
execute(password, keySize, ivSize, salt, hasher) {
|
||||
let _salt = salt;
|
||||
|
||||
// Generate random salt
|
||||
if (!_salt) {
|
||||
_salt = WordArray.random(64 / 8);
|
||||
}
|
||||
|
||||
// Derive key and IV
|
||||
let key;
|
||||
if (!hasher) {
|
||||
key = EvpKDFAlgo.create({ keySize: keySize + ivSize }).compute(password, _salt);
|
||||
} else {
|
||||
key = EvpKDFAlgo.create({ keySize: keySize + ivSize, hasher }).compute(password, _salt);
|
||||
}
|
||||
|
||||
// Separate key and IV
|
||||
const iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
|
||||
key.sigBytes = keySize * 4;
|
||||
|
||||
// Return params
|
||||
return CipherParams.create({ key, iv, salt: _salt });
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* A serializable cipher wrapper that derives the key from a password,
|
||||
* and returns ciphertext as a serializable cipher params object.
|
||||
*/
|
||||
export class PasswordBasedCipher extends SerializableCipher {
|
||||
/**
|
||||
* Encrypts a message using a password.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {WordArray|string} message The message to encrypt.
|
||||
* @param {string} password The password.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {CipherParams} A cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, 'password');
|
||||
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher
|
||||
* .encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
static encrypt(cipher, message, password, cfg) {
|
||||
// Apply config defaults
|
||||
const _cfg = Object.assign(new Base(), this.cfg, cfg);
|
||||
|
||||
// Derive key and other params
|
||||
const derivedParams = _cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, _cfg.salt, _cfg.hasher);
|
||||
|
||||
// Add IV to config
|
||||
_cfg.iv = derivedParams.iv;
|
||||
|
||||
// Encrypt
|
||||
const ciphertext = SerializableCipher.encrypt
|
||||
.call(this, cipher, message, derivedParams.key, _cfg);
|
||||
|
||||
// Mix in derived params
|
||||
ciphertext.mixIn(derivedParams);
|
||||
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts serialized ciphertext using a password.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
|
||||
* @param {string} password The password.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {WordArray} The plaintext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var plaintext = CryptoJS.lib.PasswordBasedCipher
|
||||
* .decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password',
|
||||
* { format: CryptoJS.format.OpenSSL });
|
||||
* var plaintext = CryptoJS.lib.PasswordBasedCipher
|
||||
* .decrypt(CryptoJS.algo.AES, ciphertextParams, 'password',
|
||||
* { format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
static decrypt(cipher, ciphertext, password, cfg) {
|
||||
let _ciphertext = ciphertext;
|
||||
|
||||
// Apply config defaults
|
||||
const _cfg = Object.assign(new Base(), this.cfg, cfg);
|
||||
|
||||
// Convert string to CipherParams
|
||||
_ciphertext = this._parse(_ciphertext, _cfg.format);
|
||||
|
||||
// Derive key and other params
|
||||
const derivedParams = _cfg.kdf
|
||||
.execute(password, cipher.keySize, cipher.ivSize, _ciphertext.salt, _cfg.hasher);
|
||||
|
||||
// Add IV to config
|
||||
_cfg.iv = derivedParams.iv;
|
||||
|
||||
// Decrypt
|
||||
const plaintext = SerializableCipher.decrypt
|
||||
.call(this, cipher, _ciphertext, derivedParams.key, _cfg);
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {KDF} kdf
|
||||
* The key derivation function to use to generate a key and IV from a password.
|
||||
* Default: OpenSSL
|
||||
*/
|
||||
PasswordBasedCipher.cfg = Object.assign(SerializableCipher.cfg, { kdf: OpenSSLKdf });
|
||||
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* Base class for inheritance.
|
||||
*/
|
||||
export class Base {
|
||||
/**
|
||||
* Extends this object and runs the init method.
|
||||
* Arguments to create() will be passed to init().
|
||||
*
|
||||
* @return {Object} The new object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var instance = MyType.create();
|
||||
*/
|
||||
static create(...args: any[]): Base;
|
||||
/**
|
||||
* Copies properties into this object.
|
||||
*
|
||||
* @param {Object} properties The properties to mix in.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* MyType.mixIn({
|
||||
* field: 'value'
|
||||
* });
|
||||
*/
|
||||
mixIn(properties: object): Base;
|
||||
/**
|
||||
* Creates a copy of this object.
|
||||
*
|
||||
* @return {Object} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = instance.clone();
|
||||
*/
|
||||
clone(): Base;
|
||||
}
|
||||
/**
|
||||
* An array of 32-bit words.
|
||||
*
|
||||
* @property {Array} words The array of 32-bit words.
|
||||
* @property {number} sigBytes The number of significant bytes in this word array.
|
||||
*/
|
||||
export class WordArray extends Base {
|
||||
/**
|
||||
* Creates a word array filled with random bytes.
|
||||
*
|
||||
* @param {number} nBytes The number of random bytes to generate.
|
||||
*
|
||||
* @return {WordArray} The random word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.lib.WordArray.random(16);
|
||||
*/
|
||||
static random(nBytes: number): WordArray;
|
||||
/**
|
||||
* Initializes a newly created word array.
|
||||
*
|
||||
* @param {Array} words (Optional) An array of 32-bit words.
|
||||
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.lib.WordArray.create();
|
||||
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
|
||||
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
|
||||
*/
|
||||
static create(
|
||||
words?: Array<number> | ArrayBuffer | Uint8Array | Int8Array | Uint8ClampedArray
|
||||
| Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array,
|
||||
sigBytes?: number,
|
||||
): WordArray;
|
||||
constructor(
|
||||
words?: Array<number> | ArrayBuffer | Uint8Array | Int8Array | Uint8ClampedArray
|
||||
| Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array,
|
||||
sigBytes?: number,
|
||||
);
|
||||
words: Array<number>;
|
||||
sigBytes: number;
|
||||
/**
|
||||
* Converts this word array to a string.
|
||||
*
|
||||
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
|
||||
*
|
||||
* @return {string} The stringified word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var string = wordArray + '';
|
||||
* var string = wordArray.toString();
|
||||
* var string = wordArray.toString(CryptoJS.enc.Utf8);
|
||||
*/
|
||||
toString(encoder?: Encoder): string;
|
||||
/**
|
||||
* Concatenates a word array to this word array.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array to append.
|
||||
*
|
||||
* @return {WordArray} This word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* wordArray1.concat(wordArray2);
|
||||
*/
|
||||
concat(wordArray: WordArray): WordArray;
|
||||
/**
|
||||
* Removes insignificant bits.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* wordArray.clamp();
|
||||
*/
|
||||
clamp(): void;
|
||||
/**
|
||||
* Creates a copy of this word array.
|
||||
*
|
||||
* @return {WordArray} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = wordArray.clone();
|
||||
*/
|
||||
clone(): WordArray;
|
||||
}
|
||||
export interface Encoder {
|
||||
stringify(wordArray: WordArray): string;
|
||||
parse(str: string): WordArray;
|
||||
}
|
||||
export const Hex: Encoder;
|
||||
export const Latin1: Encoder;
|
||||
export const Utf8: Encoder;
|
||||
/**
|
||||
* Abstract buffered block algorithm template.
|
||||
*
|
||||
* The property blockSize must be implemented in a concrete subtype.
|
||||
*
|
||||
* @property {number} _minBufferSize
|
||||
*
|
||||
* The number of blocks that should be kept unprocessed in the buffer. Default: 0
|
||||
*/
|
||||
export class BufferedBlockAlgorithm extends Base {
|
||||
_minBufferSize: number;
|
||||
/**
|
||||
* Resets this block algorithm's data buffer to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* bufferedBlockAlgorithm.reset();
|
||||
*/
|
||||
reset(): void;
|
||||
_data: WordArray;
|
||||
_nDataBytes: number;
|
||||
/**
|
||||
* Adds new data to this block algorithm's buffer.
|
||||
*
|
||||
* @param {WordArray|string} data
|
||||
*
|
||||
* The data to append. Strings are converted to a WordArray using UTF-8.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* bufferedBlockAlgorithm._append('data');
|
||||
* bufferedBlockAlgorithm._append(wordArray);
|
||||
*/
|
||||
_append(data: WordArray | string): void;
|
||||
/**
|
||||
* Processes available data blocks.
|
||||
*
|
||||
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
|
||||
*
|
||||
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
|
||||
*
|
||||
* @return {WordArray} The processed data.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var processedData = bufferedBlockAlgorithm._process();
|
||||
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
|
||||
*/
|
||||
_process(doFlush?: boolean): WordArray;
|
||||
/**
|
||||
* Creates a copy of this object.
|
||||
*
|
||||
* @return {Object} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = bufferedBlockAlgorithm.clone();
|
||||
*/
|
||||
clone(): BufferedBlockAlgorithm;
|
||||
}
|
||||
export interface HasherCfg {
|
||||
// SHA3
|
||||
outputLength?: number
|
||||
}
|
||||
export type HashFn = (message: WordArray | string, cfg?: HasherCfg) => WordArray;
|
||||
export type HMACHashFn = (message: WordArray | string, key: WordArray | string) => WordArray;
|
||||
/**
|
||||
* Abstract hasher template.
|
||||
*
|
||||
* @property {number} blockSize
|
||||
*
|
||||
* The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
|
||||
*/
|
||||
export class Hasher extends BufferedBlockAlgorithm {
|
||||
/**
|
||||
* Creates a shortcut function to a hasher's object interface.
|
||||
*
|
||||
* @param {Hasher} SubHasher The hasher to create a helper for.
|
||||
*
|
||||
* @return {Function} The shortcut function.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
|
||||
*/
|
||||
static _createHelper(SubHasher: Hasher): HashFn;
|
||||
/**
|
||||
* Creates a shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {Hasher} SubHasher The hasher to use in this HMAC helper.
|
||||
*
|
||||
* @return {Function} The shortcut function.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
|
||||
*/
|
||||
static _createHmacHelper(SubHasher: Hasher): HMACHashFn;
|
||||
static create(cfg?: HasherCfg): Hasher;
|
||||
constructor(cfg?: HasherCfg);
|
||||
blockSize: number;
|
||||
/**
|
||||
* Configuration options.
|
||||
*/
|
||||
cfg: Base;
|
||||
/**
|
||||
* Updates this hasher with a message.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate The message to append.
|
||||
*
|
||||
* @return {Hasher} This hasher.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hasher.update('message');
|
||||
* hasher.update(wordArray);
|
||||
*/
|
||||
update(messageUpdate: WordArray | string): Hasher;
|
||||
/**
|
||||
* Finalizes the hash computation.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate (Optional) A final message update.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = hasher.finalize();
|
||||
* var hash = hasher.finalize('message');
|
||||
* var hash = hasher.finalize(wordArray);
|
||||
*/
|
||||
finalize(messageUpdate?: WordArray | string): WordArray;
|
||||
_doReset(): void;
|
||||
_hash: WordArray;
|
||||
_doProcessBlock(M: number[], offset: number): void;
|
||||
_doFinalize(): WordArray;
|
||||
}
|
||||
/**
|
||||
* HMAC algorithm.
|
||||
*/
|
||||
export class HMAC extends Base {
|
||||
/**
|
||||
* Initializes a newly created HMAC.
|
||||
*
|
||||
* @param {Hasher} SubHasher The hash algorithm to use.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
|
||||
*/
|
||||
static create(SubHasher: Function, key: WordArray | string): HMAC;
|
||||
constructor(SubHasher: Function, key: WordArray | string);
|
||||
_hasher: Hasher;
|
||||
_oKey: WordArray;
|
||||
_iKey: WordArray;
|
||||
/**
|
||||
* Resets this HMAC to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hmacHasher.reset();
|
||||
*/
|
||||
reset(): void;
|
||||
/**
|
||||
* Updates this HMAC with a message.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate The message to append.
|
||||
*
|
||||
* @return {HMAC} This HMAC instance.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hmacHasher.update('message');
|
||||
* hmacHasher.update(wordArray);
|
||||
*/
|
||||
update(messageUpdate: WordArray | string): HMAC;
|
||||
/**
|
||||
* Finalizes the HMAC computation.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate (Optional) A final message update.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = hmacHasher.finalize();
|
||||
* var hmac = hmacHasher.finalize('message');
|
||||
* var hmac = hmacHasher.finalize(wordArray);
|
||||
*/
|
||||
finalize(messageUpdate?: WordArray | string): WordArray;
|
||||
}
|
||||
export interface KDFCfg {
|
||||
// EvpKDF
|
||||
keySize?: number;
|
||||
hasher?: Function;
|
||||
iterations?: number;
|
||||
}
|
||||
export type KDFFn = (password: WordArray | string, salt: WordArray | string, cfg?: KDFCfg) => WordArray;
|
||||
@@ -0,0 +1,800 @@
|
||||
/* eslint-disable no-use-before-define */
|
||||
|
||||
const crypto =
|
||||
(typeof globalThis != 'undefined' ? globalThis : void 0)?.crypto ||
|
||||
(typeof global != 'undefined' ? global : void 0)?.crypto ||
|
||||
(typeof window != 'undefined' ? window : void 0)?.crypto ||
|
||||
(typeof self != 'undefined' ? self : void 0)?.crypto ||
|
||||
(typeof frames != 'undefined' ? frames : void 0)?.[0]?.crypto;
|
||||
|
||||
let randomWordArray;
|
||||
|
||||
if (crypto) {
|
||||
randomWordArray = (nBytes) => {
|
||||
const words = [];
|
||||
|
||||
for (let i = 0, rcache; i < nBytes; i += 4) {
|
||||
words.push(crypto.getRandomValues(new Uint32Array(1))[0]);
|
||||
}
|
||||
|
||||
return new WordArray(words, nBytes);
|
||||
}
|
||||
} else {
|
||||
// Because there is no global crypto property in this context, cryptographically unsafe Math.random() is used.
|
||||
|
||||
randomWordArray = (nBytes) => {
|
||||
const words = [];
|
||||
|
||||
const r = (m_w) => {
|
||||
let _m_w = m_w;
|
||||
let _m_z = 0x3ade68b1;
|
||||
const mask = 0xffffffff;
|
||||
|
||||
return () => {
|
||||
_m_z = (0x9069 * (_m_z & 0xFFFF) + (_m_z >> 0x10)) & mask;
|
||||
_m_w = (0x4650 * (_m_w & 0xFFFF) + (_m_w >> 0x10)) & mask;
|
||||
let result = ((_m_z << 0x10) + _m_w) & mask;
|
||||
result /= 0x100000000;
|
||||
result += 0.5;
|
||||
return result * (Math.random() > 0.5 ? 1 : -1);
|
||||
};
|
||||
};
|
||||
|
||||
for (let i = 0, rcache; i < nBytes; i += 4) {
|
||||
const _r = r((rcache || Math.random()) * 0x100000000);
|
||||
|
||||
rcache = _r() * 0x3ade67b7;
|
||||
words.push((_r() * 0x100000000) | 0);
|
||||
}
|
||||
|
||||
return new WordArray(words, nBytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for inheritance.
|
||||
*/
|
||||
export class Base {
|
||||
/**
|
||||
* Extends this object and runs the init method.
|
||||
* Arguments to create() will be passed to init().
|
||||
*
|
||||
* @return {Object} The new object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var instance = MyType.create();
|
||||
*/
|
||||
static create(...args) {
|
||||
return new this(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies properties into this object.
|
||||
*
|
||||
* @param {Object} properties The properties to mix in.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* MyType.mixIn({
|
||||
* field: 'value'
|
||||
* });
|
||||
*/
|
||||
mixIn(properties) {
|
||||
return Object.assign(this, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this object.
|
||||
*
|
||||
* @return {Object} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = instance.clone();
|
||||
*/
|
||||
clone() {
|
||||
const clone = new this.constructor();
|
||||
Object.assign(clone, this);
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of 32-bit words.
|
||||
*
|
||||
* @property {Array} words The array of 32-bit words.
|
||||
* @property {number} sigBytes The number of significant bytes in this word array.
|
||||
*/
|
||||
export class WordArray extends Base {
|
||||
/**
|
||||
* Initializes a newly created word array.
|
||||
*
|
||||
* @param {Array} words (Optional) An array of 32-bit words.
|
||||
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.lib.WordArray.create();
|
||||
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
|
||||
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
|
||||
*/
|
||||
constructor(words = [], sigBytes = words.length * 4) {
|
||||
super();
|
||||
|
||||
let typedArray = words;
|
||||
// Convert buffers to uint8
|
||||
if (typedArray instanceof ArrayBuffer) {
|
||||
typedArray = new Uint8Array(typedArray);
|
||||
}
|
||||
|
||||
// Convert other array views to uint8
|
||||
if (
|
||||
typedArray instanceof Int8Array
|
||||
|| typedArray instanceof Uint8ClampedArray
|
||||
|| typedArray instanceof Int16Array
|
||||
|| typedArray instanceof Uint16Array
|
||||
|| typedArray instanceof Int32Array
|
||||
|| typedArray instanceof Uint32Array
|
||||
|| typedArray instanceof Float32Array
|
||||
|| typedArray instanceof Float64Array
|
||||
) {
|
||||
typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
|
||||
}
|
||||
|
||||
// Handle Uint8Array
|
||||
if (typedArray instanceof Uint8Array) {
|
||||
// Shortcut
|
||||
const typedArrayByteLength = typedArray.byteLength;
|
||||
|
||||
// Extract bytes
|
||||
const _words = [];
|
||||
for (let i = 0; i < typedArrayByteLength; i += 1) {
|
||||
_words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8);
|
||||
}
|
||||
|
||||
// Initialize this word array
|
||||
this.words = _words;
|
||||
this.sigBytes = typedArrayByteLength;
|
||||
} else {
|
||||
// Else call normal init
|
||||
this.words = words;
|
||||
this.sigBytes = sigBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a word array filled with random bytes.
|
||||
*
|
||||
* @param {number} nBytes The number of random bytes to generate.
|
||||
*
|
||||
* @return {WordArray} The random word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.lib.WordArray.random(16);
|
||||
*/
|
||||
static random = randomWordArray;
|
||||
|
||||
/**
|
||||
* Converts this word array to a string.
|
||||
*
|
||||
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
|
||||
*
|
||||
* @return {string} The stringified word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var string = wordArray + '';
|
||||
* var string = wordArray.toString();
|
||||
* var string = wordArray.toString(CryptoJS.enc.Utf8);
|
||||
*/
|
||||
toString(encoder = Hex) {
|
||||
return encoder.stringify(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates a word array to this word array.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array to append.
|
||||
*
|
||||
* @return {WordArray} This word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* wordArray1.concat(wordArray2);
|
||||
*/
|
||||
concat(wordArray) {
|
||||
// Shortcuts
|
||||
const thisWords = this.words;
|
||||
const thatWords = wordArray.words;
|
||||
const thisSigBytes = this.sigBytes;
|
||||
const thatSigBytes = wordArray.sigBytes;
|
||||
|
||||
// Clamp excess bits
|
||||
this.clamp();
|
||||
|
||||
// Concat
|
||||
if (thisSigBytes % 4) {
|
||||
// Copy one byte at a time
|
||||
for (let i = 0; i < thatSigBytes; i += 1) {
|
||||
const thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
|
||||
}
|
||||
} else {
|
||||
// Copy one word at a time
|
||||
for (let i = 0; i < thatSigBytes; i += 4) {
|
||||
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
|
||||
}
|
||||
}
|
||||
this.sigBytes += thatSigBytes;
|
||||
|
||||
// Chainable
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes insignificant bits.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* wordArray.clamp();
|
||||
*/
|
||||
clamp() {
|
||||
// Shortcuts
|
||||
const { words, sigBytes } = this;
|
||||
|
||||
// Clamp
|
||||
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
|
||||
words.length = Math.ceil(sigBytes / 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this word array.
|
||||
*
|
||||
* @return {WordArray} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = wordArray.clone();
|
||||
*/
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
clone.words = this.words.slice(0);
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex encoding strategy.
|
||||
*/
|
||||
export const Hex = {
|
||||
/**
|
||||
* Converts a word array to a hex string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The hex string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hexString = CryptoJS.enc.Hex.stringify(wordArray);
|
||||
*/
|
||||
stringify(wordArray) {
|
||||
// Shortcuts
|
||||
const { words, sigBytes } = wordArray;
|
||||
|
||||
// Convert
|
||||
const hexChars = [];
|
||||
for (let i = 0; i < sigBytes; i += 1) {
|
||||
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
hexChars.push((bite >>> 4).toString(16));
|
||||
hexChars.push((bite & 0x0f).toString(16));
|
||||
}
|
||||
|
||||
return hexChars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a hex string to a word array.
|
||||
*
|
||||
* @param {string} hexStr The hex string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Hex.parse(hexString);
|
||||
*/
|
||||
parse(hexStr) {
|
||||
// Shortcut
|
||||
const hexStrLength = hexStr.length;
|
||||
|
||||
// Convert
|
||||
const words = [];
|
||||
for (let i = 0; i < hexStrLength; i += 2) {
|
||||
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
|
||||
}
|
||||
|
||||
return new WordArray(words, hexStrLength / 2);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Latin1 encoding strategy.
|
||||
*/
|
||||
export const Latin1 = {
|
||||
/**
|
||||
* Converts a word array to a Latin1 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The Latin1 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
|
||||
*/
|
||||
stringify(wordArray) {
|
||||
// Shortcuts
|
||||
const { words, sigBytes } = wordArray;
|
||||
|
||||
// Convert
|
||||
const latin1Chars = [];
|
||||
for (let i = 0; i < sigBytes; i += 1) {
|
||||
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
latin1Chars.push(String.fromCharCode(bite));
|
||||
}
|
||||
|
||||
return latin1Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a Latin1 string to a word array.
|
||||
*
|
||||
* @param {string} latin1Str The Latin1 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
|
||||
*/
|
||||
parse(latin1Str) {
|
||||
// Shortcut
|
||||
const latin1StrLength = latin1Str.length;
|
||||
|
||||
// Convert
|
||||
const words = [];
|
||||
for (let i = 0; i < latin1StrLength; i += 1) {
|
||||
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
|
||||
}
|
||||
|
||||
return new WordArray(words, latin1StrLength);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* UTF-8 encoding strategy.
|
||||
*/
|
||||
export const Utf8 = {
|
||||
/**
|
||||
* Converts a word array to a UTF-8 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-8 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
|
||||
*/
|
||||
stringify(wordArray) {
|
||||
try {
|
||||
return decodeURIComponent(escape(Latin1.stringify(wordArray)));
|
||||
} catch (e) {
|
||||
throw new Error('Malformed UTF-8 data');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-8 string to a word array.
|
||||
*
|
||||
* @param {string} utf8Str The UTF-8 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
|
||||
*/
|
||||
parse(utf8Str) {
|
||||
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract buffered block algorithm template.
|
||||
*
|
||||
* The property blockSize must be implemented in a concrete subtype.
|
||||
*
|
||||
* @property {number} _minBufferSize
|
||||
*
|
||||
* The number of blocks that should be kept unprocessed in the buffer. Default: 0
|
||||
*/
|
||||
export class BufferedBlockAlgorithm extends Base {
|
||||
constructor() {
|
||||
super();
|
||||
this._minBufferSize = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this block algorithm's data buffer to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* bufferedBlockAlgorithm.reset();
|
||||
*/
|
||||
reset() {
|
||||
// Initial values
|
||||
this._data = new WordArray();
|
||||
this._nDataBytes = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new data to this block algorithm's buffer.
|
||||
*
|
||||
* @param {WordArray|string} data
|
||||
*
|
||||
* The data to append. Strings are converted to a WordArray using UTF-8.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* bufferedBlockAlgorithm._append('data');
|
||||
* bufferedBlockAlgorithm._append(wordArray);
|
||||
*/
|
||||
_append(data) {
|
||||
let m_data = data;
|
||||
|
||||
// Convert string to WordArray, else assume WordArray already
|
||||
if (typeof m_data === 'string') {
|
||||
m_data = Utf8.parse(m_data);
|
||||
}
|
||||
|
||||
// Append
|
||||
this._data.concat(m_data);
|
||||
this._nDataBytes += m_data.sigBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes available data blocks.
|
||||
*
|
||||
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
|
||||
*
|
||||
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
|
||||
*
|
||||
* @return {WordArray} The processed data.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var processedData = bufferedBlockAlgorithm._process();
|
||||
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
|
||||
*/
|
||||
_process(doFlush) {
|
||||
let processedWords;
|
||||
|
||||
// Shortcuts
|
||||
const { _data: data, blockSize } = this;
|
||||
const dataWords = data.words;
|
||||
const dataSigBytes = data.sigBytes;
|
||||
const blockSizeBytes = blockSize * 4;
|
||||
|
||||
// Count blocks ready
|
||||
let nBlocksReady = dataSigBytes / blockSizeBytes;
|
||||
if (doFlush) {
|
||||
// Round up to include partial blocks
|
||||
nBlocksReady = Math.ceil(nBlocksReady);
|
||||
} else {
|
||||
// Round down to include only full blocks,
|
||||
// less the number of blocks that must remain in the buffer
|
||||
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
|
||||
}
|
||||
|
||||
// Count words ready
|
||||
const nWordsReady = nBlocksReady * blockSize;
|
||||
|
||||
// Count bytes ready
|
||||
const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
|
||||
|
||||
// Process blocks
|
||||
if (nWordsReady) {
|
||||
for (let offset = 0; offset < nWordsReady; offset += blockSize) {
|
||||
// Perform concrete-algorithm logic
|
||||
this._doProcessBlock(dataWords, offset);
|
||||
}
|
||||
|
||||
// Remove processed words
|
||||
processedWords = dataWords.splice(0, nWordsReady);
|
||||
data.sigBytes -= nBytesReady;
|
||||
}
|
||||
|
||||
// Return processed words
|
||||
return new WordArray(processedWords, nBytesReady);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this object.
|
||||
*
|
||||
* @return {Object} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = bufferedBlockAlgorithm.clone();
|
||||
*/
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
clone._data = this._data.clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract hasher template.
|
||||
*
|
||||
* @property {number} blockSize
|
||||
*
|
||||
* The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
|
||||
*/
|
||||
export class Hasher extends BufferedBlockAlgorithm {
|
||||
constructor(cfg) {
|
||||
super();
|
||||
|
||||
this.blockSize = 512 / 32;
|
||||
|
||||
/**
|
||||
* Configuration options.
|
||||
*/
|
||||
this.cfg = Object.assign(new Base(), cfg);
|
||||
|
||||
// Set initial values
|
||||
this.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a shortcut function to a hasher's object interface.
|
||||
*
|
||||
* @param {Hasher} SubHasher The hasher to create a helper for.
|
||||
*
|
||||
* @return {Function} The shortcut function.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
|
||||
*/
|
||||
static _createHelper(SubHasher) {
|
||||
return (message, cfg) => new SubHasher(cfg).finalize(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {Hasher} SubHasher The hasher to use in this HMAC helper.
|
||||
*
|
||||
* @return {Function} The shortcut function.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
|
||||
*/
|
||||
static _createHmacHelper(SubHasher) {
|
||||
return (message, key) => new HMAC(SubHasher, key).finalize(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this hasher to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hasher.reset();
|
||||
*/
|
||||
reset() {
|
||||
// Reset data buffer
|
||||
super.reset.call(this);
|
||||
|
||||
// Perform concrete-hasher logic
|
||||
this._doReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this hasher with a message.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate The message to append.
|
||||
*
|
||||
* @return {Hasher} This hasher.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hasher.update('message');
|
||||
* hasher.update(wordArray);
|
||||
*/
|
||||
update(messageUpdate) {
|
||||
// Append
|
||||
this._append(messageUpdate);
|
||||
|
||||
// Update the hash
|
||||
this._process();
|
||||
|
||||
// Chainable
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the hash computation.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate (Optional) A final message update.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = hasher.finalize();
|
||||
* var hash = hasher.finalize('message');
|
||||
* var hash = hasher.finalize(wordArray);
|
||||
*/
|
||||
finalize(messageUpdate) {
|
||||
// Final message update
|
||||
if (messageUpdate) {
|
||||
this._append(messageUpdate);
|
||||
}
|
||||
|
||||
// Perform concrete-hasher logic
|
||||
const hash = this._doFinalize();
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC algorithm.
|
||||
*/
|
||||
export class HMAC extends Base {
|
||||
/**
|
||||
* Initializes a newly created HMAC.
|
||||
*
|
||||
* @param {Hasher} SubHasher The hash algorithm to use.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
|
||||
*/
|
||||
constructor(SubHasher, key) {
|
||||
super();
|
||||
|
||||
const hasher = new SubHasher();
|
||||
this._hasher = hasher;
|
||||
|
||||
// Convert string to WordArray, else assume WordArray already
|
||||
let _key = key;
|
||||
if (typeof _key === 'string') {
|
||||
_key = Utf8.parse(_key);
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
const hasherBlockSize = hasher.blockSize;
|
||||
const hasherBlockSizeBytes = hasherBlockSize * 4;
|
||||
|
||||
// Allow arbitrary length keys
|
||||
if (_key.sigBytes > hasherBlockSizeBytes) {
|
||||
_key = hasher.finalize(key);
|
||||
}
|
||||
|
||||
// Clamp excess bits
|
||||
_key.clamp();
|
||||
|
||||
// Clone key for inner and outer pads
|
||||
const oKey = _key.clone();
|
||||
this._oKey = oKey;
|
||||
const iKey = _key.clone();
|
||||
this._iKey = iKey;
|
||||
|
||||
// Shortcuts
|
||||
const oKeyWords = oKey.words;
|
||||
const iKeyWords = iKey.words;
|
||||
|
||||
// XOR keys with pad constants
|
||||
for (let i = 0; i < hasherBlockSize; i += 1) {
|
||||
oKeyWords[i] ^= 0x5c5c5c5c;
|
||||
iKeyWords[i] ^= 0x36363636;
|
||||
}
|
||||
oKey.sigBytes = hasherBlockSizeBytes;
|
||||
iKey.sigBytes = hasherBlockSizeBytes;
|
||||
|
||||
// Set initial values
|
||||
this.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this HMAC to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hmacHasher.reset();
|
||||
*/
|
||||
reset() {
|
||||
// Shortcut
|
||||
const hasher = this._hasher;
|
||||
|
||||
// Reset
|
||||
hasher.reset();
|
||||
hasher.update(this._iKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this HMAC with a message.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate The message to append.
|
||||
*
|
||||
* @return {HMAC} This HMAC instance.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hmacHasher.update('message');
|
||||
* hmacHasher.update(wordArray);
|
||||
*/
|
||||
update(messageUpdate) {
|
||||
this._hasher.update(messageUpdate);
|
||||
|
||||
// Chainable
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the HMAC computation.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate (Optional) A final message update.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = hmacHasher.finalize();
|
||||
* var hmac = hmacHasher.finalize('message');
|
||||
* var hmac = hmacHasher.finalize(wordArray);
|
||||
*/
|
||||
finalize(messageUpdate) {
|
||||
// Shortcut
|
||||
const hasher = this._hasher;
|
||||
|
||||
// Compute HMAC
|
||||
const innerHash = hasher.finalize(messageUpdate);
|
||||
hasher.reset();
|
||||
const hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
|
||||
|
||||
return hmac;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export function parseLoop(base64Str: string, base64StrLength: number, reverseMap: number[]): WordArray;
|
||||
/**
|
||||
* Base64 encoding strategy.
|
||||
*/
|
||||
export const Base64: Encoder;
|
||||
import { Encoder } from './core.js';
|
||||
import { WordArray } from './core.js';
|
||||
@@ -0,0 +1,111 @@
|
||||
import {
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
|
||||
export const parseLoop = (base64Str, base64StrLength, reverseMap) => {
|
||||
const words = [];
|
||||
let nBytes = 0;
|
||||
for (let i = 0; i < base64StrLength; i += 1) {
|
||||
if (i % 4) {
|
||||
const bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
|
||||
const bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
|
||||
const bitsCombined = bits1 | bits2;
|
||||
words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
|
||||
nBytes += 1;
|
||||
}
|
||||
}
|
||||
return WordArray.create(words, nBytes);
|
||||
};
|
||||
|
||||
/**
|
||||
* Base64 encoding strategy.
|
||||
*/
|
||||
export const Base64 = {
|
||||
/**
|
||||
* Converts a word array to a Base64 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The Base64 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const base64String = CryptoJS.enc.Base64.stringify(wordArray);
|
||||
*/
|
||||
stringify(wordArray) {
|
||||
// Shortcuts
|
||||
const { words, sigBytes } = wordArray;
|
||||
const map = this._map;
|
||||
|
||||
// Clamp excess bits
|
||||
wordArray.clamp();
|
||||
|
||||
// Convert
|
||||
const base64Chars = [];
|
||||
for (let i = 0; i < sigBytes; i += 3) {
|
||||
const byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
const byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
|
||||
const byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
|
||||
|
||||
const triplet = (byte1 << 16) | (byte2 << 8) | byte3;
|
||||
|
||||
for (let j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j += 1) {
|
||||
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
// Add padding
|
||||
const paddingChar = map.charAt(64);
|
||||
if (paddingChar) {
|
||||
while (base64Chars.length % 4) {
|
||||
base64Chars.push(paddingChar);
|
||||
}
|
||||
}
|
||||
|
||||
return base64Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a Base64 string to a word array.
|
||||
*
|
||||
* @param {string} base64Str The Base64 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const wordArray = CryptoJS.enc.Base64.parse(base64String);
|
||||
*/
|
||||
parse(base64Str) {
|
||||
// Shortcuts
|
||||
let base64StrLength = base64Str.length;
|
||||
const map = this._map;
|
||||
let reverseMap = this._reverseMap;
|
||||
|
||||
if (!reverseMap) {
|
||||
this._reverseMap = [];
|
||||
reverseMap = this._reverseMap;
|
||||
for (let j = 0; j < map.length; j += 1) {
|
||||
reverseMap[map.charCodeAt(j)] = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore padding
|
||||
const paddingChar = map.charAt(64);
|
||||
if (paddingChar) {
|
||||
const paddingIndex = base64Str.indexOf(paddingChar);
|
||||
if (paddingIndex !== -1) {
|
||||
base64StrLength = paddingIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert
|
||||
return parseLoop(base64Str, base64StrLength, reverseMap);
|
||||
},
|
||||
|
||||
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Base64url encoding strategy.
|
||||
*/
|
||||
export const Base64url: Encoder;
|
||||
import { Encoder } from './core.js';
|
||||
@@ -0,0 +1,105 @@
|
||||
import {
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
import {
|
||||
parseLoop,
|
||||
} from './enc-base64.js'
|
||||
|
||||
/**
|
||||
* Base64url encoding strategy.
|
||||
*/
|
||||
export const Base64url = {
|
||||
/**
|
||||
* Converts a word array to a Base64url string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @param {boolean} urlSafe Whether to use url safe.
|
||||
*
|
||||
* @return {string} The Base64url string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const base64String = CryptoJS.enc.Base64.stringify(wordArray);
|
||||
*/
|
||||
stringify(wordArray, urlSafe = true) {
|
||||
// Shortcuts
|
||||
const { words, sigBytes } = wordArray;
|
||||
const map = urlSafe ? this._safeMap : this._map;
|
||||
|
||||
// Clamp excess bits
|
||||
wordArray.clamp();
|
||||
|
||||
// Convert
|
||||
const base64Chars = [];
|
||||
for (let i = 0; i < sigBytes; i += 3) {
|
||||
const byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
const byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
|
||||
const byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
|
||||
|
||||
const triplet = (byte1 << 16) | (byte2 << 8) | byte3;
|
||||
|
||||
for (let j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j += 1) {
|
||||
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
// Add padding
|
||||
const paddingChar = map.charAt(64);
|
||||
if (paddingChar) {
|
||||
while (base64Chars.length % 4) {
|
||||
base64Chars.push(paddingChar);
|
||||
}
|
||||
}
|
||||
|
||||
return base64Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a Base64url string to a word array.
|
||||
*
|
||||
* @param {string} base64Str The Base64url string.
|
||||
*
|
||||
* @param {boolean} urlSafe Whether to use url safe.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const wordArray = CryptoJS.enc.Base64.parse(base64String);
|
||||
*/
|
||||
parse(base64Str, urlSafe = true) {
|
||||
// Shortcuts
|
||||
let base64StrLength = base64Str.length;
|
||||
const map = urlSafe ? this._safeMap : this._map;
|
||||
let reverseMap = this._reverseMap;
|
||||
|
||||
if (!reverseMap) {
|
||||
this._reverseMap = [];
|
||||
reverseMap = this._reverseMap;
|
||||
for (let j = 0; j < map.length; j += 1) {
|
||||
reverseMap[map.charCodeAt(j)] = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore padding
|
||||
const paddingChar = map.charAt(64);
|
||||
if (paddingChar) {
|
||||
const paddingIndex = base64Str.indexOf(paddingChar);
|
||||
if (paddingIndex !== -1) {
|
||||
base64StrLength = paddingIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert
|
||||
return parseLoop(base64Str, base64StrLength, reverseMap);
|
||||
},
|
||||
|
||||
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
|
||||
|
||||
_safeMap: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
export const Utf16: Encoder;
|
||||
/**
|
||||
* UTF-16 BE encoding strategy.
|
||||
*/
|
||||
export const Utf16BE: Encoder;
|
||||
/**
|
||||
* UTF-16 LE encoding strategy.
|
||||
*/
|
||||
export const Utf16LE: Encoder;
|
||||
import { Encoder } from './core.js';
|
||||
@@ -0,0 +1,122 @@
|
||||
import {
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
|
||||
const swapEndian = word => ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff);
|
||||
|
||||
/**
|
||||
* UTF-16 BE encoding strategy.
|
||||
*/
|
||||
export const Utf16BE = {
|
||||
/**
|
||||
* Converts a word array to a UTF-16 BE string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-16 BE string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const utf16String = CryptoJS.enc.Utf16.stringify(wordArray);
|
||||
*/
|
||||
stringify(wordArray) {
|
||||
// Shortcuts
|
||||
const { words, sigBytes } = wordArray;
|
||||
|
||||
// Convert
|
||||
const utf16Chars = [];
|
||||
for (let i = 0; i < sigBytes; i += 2) {
|
||||
const codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff;
|
||||
utf16Chars.push(String.fromCharCode(codePoint));
|
||||
}
|
||||
|
||||
return utf16Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-16 BE string to a word array.
|
||||
*
|
||||
* @param {string} utf16Str The UTF-16 BE string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const wordArray = CryptoJS.enc.Utf16.parse(utf16String);
|
||||
*/
|
||||
parse(utf16Str) {
|
||||
// Shortcut
|
||||
const utf16StrLength = utf16Str.length;
|
||||
|
||||
// Convert
|
||||
const words = [];
|
||||
for (let i = 0; i < utf16StrLength; i += 1) {
|
||||
words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16);
|
||||
}
|
||||
|
||||
return WordArray.create(words, utf16StrLength * 2);
|
||||
},
|
||||
};
|
||||
export const Utf16 = Utf16BE;
|
||||
|
||||
/**
|
||||
* UTF-16 LE encoding strategy.
|
||||
*/
|
||||
export const Utf16LE = {
|
||||
/**
|
||||
* Converts a word array to a UTF-16 LE string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-16 LE string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray);
|
||||
*/
|
||||
stringify(wordArray) {
|
||||
// Shortcuts
|
||||
const { words, sigBytes } = wordArray;
|
||||
|
||||
// Convert
|
||||
const utf16Chars = [];
|
||||
for (let i = 0; i < sigBytes; i += 2) {
|
||||
const codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff);
|
||||
utf16Chars.push(String.fromCharCode(codePoint));
|
||||
}
|
||||
|
||||
return utf16Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-16 LE string to a word array.
|
||||
*
|
||||
* @param {string} utf16Str The UTF-16 LE string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str);
|
||||
*/
|
||||
parse(utf16Str) {
|
||||
// Shortcut
|
||||
const utf16StrLength = utf16Str.length;
|
||||
|
||||
// Convert
|
||||
const words = [];
|
||||
for (let i = 0; i < utf16StrLength; i += 1) {
|
||||
words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16));
|
||||
}
|
||||
|
||||
return WordArray.create(words, utf16StrLength * 2);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* This key derivation function is meant to conform with EVP_BytesToKey.
|
||||
* www.openssl.org/docs/crypto/EVP_BytesToKey.html
|
||||
*/
|
||||
export class EvpKDFAlgo extends Base {
|
||||
static create(cfg?: KDFCfg): EvpKDFAlgo;
|
||||
constructor(cfg?: KDFCfg);
|
||||
compute(password: WordArray | string, salt: WordArray | string): WordArray;
|
||||
}
|
||||
/**
|
||||
* Derives a key from a password.
|
||||
*
|
||||
* @param {WordArray|string} password The password.
|
||||
* @param {WordArray|string} salt A salt.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this computation.
|
||||
*
|
||||
* @return {WordArray} The derived key.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var key = CryptoJS.EvpKDF(password, salt);
|
||||
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
|
||||
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
|
||||
*/
|
||||
export const EvpKDF: KDFFn;
|
||||
import { Base } from './core.js';
|
||||
import { WordArray } from './core.js';
|
||||
import { KDFCfg } from './core.js';
|
||||
import { KDFFn } from './core.js';
|
||||
@@ -0,0 +1,111 @@
|
||||
import {
|
||||
Base,
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
import { MD5Algo } from './md5.js';
|
||||
|
||||
/**
|
||||
* This key derivation function is meant to conform with EVP_BytesToKey.
|
||||
* www.openssl.org/docs/crypto/EVP_BytesToKey.html
|
||||
*/
|
||||
export class EvpKDFAlgo extends Base {
|
||||
/**
|
||||
* Initializes a newly created key derivation function.
|
||||
*
|
||||
* @param {Object} cfg (Optional) The configuration options to use for the derivation.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const kdf = CryptoJS.algo.EvpKDF.create();
|
||||
* const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
|
||||
* const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 });
|
||||
*/
|
||||
constructor(cfg) {
|
||||
super();
|
||||
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
|
||||
* @property {Hasher} hasher The hash algorithm to use. Default: MD5
|
||||
* @property {number} iterations The number of iterations to perform. Default: 1
|
||||
*/
|
||||
this.cfg = Object.assign(
|
||||
new Base(),
|
||||
{
|
||||
keySize: 128 / 32,
|
||||
hasher: MD5Algo,
|
||||
iterations: 1,
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a key from a password.
|
||||
*
|
||||
* @param {WordArray|string} password The password.
|
||||
* @param {WordArray|string} salt A salt.
|
||||
*
|
||||
* @return {WordArray} The derived key.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const key = kdf.compute(password, salt);
|
||||
*/
|
||||
compute(password, salt) {
|
||||
let block;
|
||||
|
||||
// Shortcut
|
||||
const { cfg } = this;
|
||||
|
||||
// Init hasher
|
||||
const hasher = cfg.hasher.create();
|
||||
|
||||
// Initial values
|
||||
const derivedKey = WordArray.create();
|
||||
|
||||
// Shortcuts
|
||||
const derivedKeyWords = derivedKey.words;
|
||||
const { keySize, iterations } = cfg;
|
||||
|
||||
// Generate key
|
||||
while (derivedKeyWords.length < keySize) {
|
||||
if (block) {
|
||||
hasher.update(block);
|
||||
}
|
||||
block = hasher.update(password).finalize(salt);
|
||||
hasher.reset();
|
||||
|
||||
// Iterations
|
||||
for (let i = 1; i < iterations; i += 1) {
|
||||
block = hasher.finalize(block);
|
||||
hasher.reset();
|
||||
}
|
||||
|
||||
derivedKey.concat(block);
|
||||
}
|
||||
derivedKey.sigBytes = keySize * 4;
|
||||
|
||||
return derivedKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a key from a password.
|
||||
*
|
||||
* @param {WordArray|string} password The password.
|
||||
* @param {WordArray|string} salt A salt.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this computation.
|
||||
*
|
||||
* @return {WordArray} The derived key.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var key = CryptoJS.EvpKDF(password, salt);
|
||||
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
|
||||
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
|
||||
*/
|
||||
export const EvpKDF = (password, salt, cfg) => EvpKDFAlgo.create(cfg).compute(password, salt);
|
||||
@@ -0,0 +1,2 @@
|
||||
export const HexFormatter: Format;
|
||||
import { Format } from './cipher-core';
|
||||
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
CipherParams,
|
||||
} from './cipher-core.js';
|
||||
import {
|
||||
Hex,
|
||||
} from './core.js';
|
||||
|
||||
export const HexFormatter = {
|
||||
/**
|
||||
* Converts the ciphertext of a cipher params object to a hexadecimally encoded string.
|
||||
*
|
||||
* @param {CipherParams} cipherParams The cipher params object.
|
||||
*
|
||||
* @return {string} The hexadecimally encoded string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hexString = CryptoJS.format.Hex.stringify(cipherParams);
|
||||
*/
|
||||
stringify(cipherParams) {
|
||||
return cipherParams.ciphertext.toString(Hex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a hexadecimally encoded ciphertext string to a cipher params object.
|
||||
*
|
||||
* @param {string} input The hexadecimally encoded string.
|
||||
*
|
||||
* @return {CipherParams} The cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipherParams = CryptoJS.format.Hex.parse(hexString);
|
||||
*/
|
||||
parse(input) {
|
||||
const ciphertext = Hex.parse(input);
|
||||
return CipherParams.create({ ciphertext });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { HMAC } from "./core.js";
|
||||
@@ -0,0 +1,3 @@
|
||||
export {
|
||||
HMAC,
|
||||
} from './core.js';
|
||||
@@ -0,0 +1,181 @@
|
||||
declare namespace _default {
|
||||
export namespace lib {
|
||||
export { Base };
|
||||
export { WordArray };
|
||||
export { BufferedBlockAlgorithm };
|
||||
export { Hasher };
|
||||
export { Cipher };
|
||||
export { StreamCipher };
|
||||
export { BlockCipherMode };
|
||||
export { BlockCipher };
|
||||
export { CipherParams };
|
||||
export { SerializableCipher };
|
||||
export { PasswordBasedCipher };
|
||||
}
|
||||
export namespace x64 {
|
||||
export { X64Word as Word };
|
||||
export { X64WordArray as WordArray };
|
||||
}
|
||||
export namespace enc {
|
||||
export { Hex };
|
||||
export { Latin1 };
|
||||
export { Utf8 };
|
||||
export { Utf16 };
|
||||
export { Utf16BE };
|
||||
export { Utf16LE };
|
||||
export { Base64 };
|
||||
export { Base64url };
|
||||
}
|
||||
export namespace algo {
|
||||
export { HMAC };
|
||||
export { MD5Algo as MD5 };
|
||||
export { SHA1Algo as SHA1 };
|
||||
export { SHA224Algo as SHA224 };
|
||||
export { SHA256Algo as SHA256 };
|
||||
export { SHA384Algo as SHA384 };
|
||||
export { SHA512Algo as SHA512 };
|
||||
export { SHA3Algo as SHA3 };
|
||||
export { RIPEMD160Algo as RIPEMD160 };
|
||||
export { PBKDF2Algo as PBKDF2 };
|
||||
export { EvpKDFAlgo as EvpKDF };
|
||||
export { AESAlgo as AES };
|
||||
export { DESAlgo as DES };
|
||||
export { TripleDESAlgo as TripleDES };
|
||||
export { RabbitAlgo as Rabbit };
|
||||
export { RabbitLegacyAlgo as RabbitLegacy };
|
||||
export { RC4Algo as RC4 };
|
||||
export { RC4DropAlgo as RC4Drop };
|
||||
export { BlowfishAlgo as Blowfish };
|
||||
}
|
||||
export namespace mode {
|
||||
export { CBC };
|
||||
export { CFB };
|
||||
export { CTR };
|
||||
export { CTRGladman };
|
||||
export { ECB };
|
||||
export { OFB };
|
||||
}
|
||||
export namespace pad {
|
||||
export { Pkcs7 };
|
||||
export { AnsiX923 };
|
||||
export { Iso10126 };
|
||||
export { Iso97971 };
|
||||
export { NoPadding };
|
||||
export { ZeroPadding };
|
||||
}
|
||||
export namespace format {
|
||||
export { OpenSSLFormatter as OpenSSL };
|
||||
export { HexFormatter as Hex };
|
||||
}
|
||||
export namespace kdf {
|
||||
export { OpenSSLKdf as OpenSSL };
|
||||
}
|
||||
export { MD5 };
|
||||
export { HmacMD5 };
|
||||
export { SHA1 };
|
||||
export { HmacSHA1 };
|
||||
export { SHA224 };
|
||||
export { HmacSHA224 };
|
||||
export { SHA256 };
|
||||
export { HmacSHA256 };
|
||||
export { SHA384 };
|
||||
export { HmacSHA384 };
|
||||
export { SHA512 };
|
||||
export { HmacSHA512 };
|
||||
export { SHA3 };
|
||||
export { HmacSHA3 };
|
||||
export { RIPEMD160 };
|
||||
export { HmacRIPEMD160 };
|
||||
export { PBKDF2 };
|
||||
export { EvpKDF };
|
||||
export { AES };
|
||||
export { DES };
|
||||
export { TripleDES };
|
||||
export { Rabbit };
|
||||
export { RabbitLegacy };
|
||||
export { RC4 };
|
||||
export { RC4Drop };
|
||||
export { Blowfish };
|
||||
}
|
||||
export default _default;
|
||||
import { Base } from './core.js';
|
||||
import { WordArray } from './core.js';
|
||||
import { BufferedBlockAlgorithm } from './core.js';
|
||||
import { Hasher } from './core.js';
|
||||
import { Cipher } from './cipher-core.js';
|
||||
import { StreamCipher } from './cipher-core.js';
|
||||
import { BlockCipherMode } from './cipher-core.js';
|
||||
import { BlockCipher } from './cipher-core.js';
|
||||
import { CipherParams } from './cipher-core.js';
|
||||
import { SerializableCipher } from './cipher-core.js';
|
||||
import { PasswordBasedCipher } from './cipher-core.js';
|
||||
import { X64Word } from './x64-core.js';
|
||||
import { X64WordArray } from './x64-core.js';
|
||||
import { Hex } from './core.js';
|
||||
import { Latin1 } from './core.js';
|
||||
import { Utf8 } from './core.js';
|
||||
import { Utf16 } from './enc-utf16.js';
|
||||
import { Utf16BE } from './enc-utf16.js';
|
||||
import { Utf16LE } from './enc-utf16.js';
|
||||
import { Base64 } from './enc-base64.js';
|
||||
import { Base64url } from './enc-base64url.js';
|
||||
import { HMAC } from './hmac.js';
|
||||
import { MD5Algo } from './md5.js';
|
||||
import { SHA1Algo } from './sha1.js';
|
||||
import { SHA224Algo } from './sha224.js';
|
||||
import { SHA256Algo } from './sha256.js';
|
||||
import { SHA384Algo } from './sha384.js';
|
||||
import { SHA512Algo } from './sha512.js';
|
||||
import { SHA3Algo } from './sha3.js';
|
||||
import { RIPEMD160Algo } from './ripemd160.js';
|
||||
import { PBKDF2Algo } from './pbkdf2.js';
|
||||
import { EvpKDFAlgo } from './evpkdf.js';
|
||||
import { AESAlgo } from './aes.js';
|
||||
import { DESAlgo } from './tripledes.js';
|
||||
import { TripleDESAlgo } from './tripledes.js';
|
||||
import { RabbitAlgo } from './rabbit.js';
|
||||
import { RabbitLegacyAlgo } from './rabbit-legacy.js';
|
||||
import { RC4Algo } from './rc4.js';
|
||||
import { RC4DropAlgo } from './rc4.js';
|
||||
import { BlowfishAlgo } from './blowfish.js';
|
||||
import { CBC } from './cipher-core.js';
|
||||
import { CFB } from './mode-cfb.js';
|
||||
import { CTR } from './mode-ctr.js';
|
||||
import { CTRGladman } from './mode-ctr-gladman.js';
|
||||
import { ECB } from './mode-ecb.js';
|
||||
import { OFB } from './mode-ofb.js';
|
||||
import { Pkcs7 } from './cipher-core.js';
|
||||
import { AnsiX923 } from './pad-ansix923.js';
|
||||
import { Iso10126 } from './pad-iso10126.js';
|
||||
import { Iso97971 } from './pad-iso97971.js';
|
||||
import { NoPadding } from './pad-nopadding.js';
|
||||
import { ZeroPadding } from './pad-zeropadding.js';
|
||||
import { OpenSSLFormatter } from './cipher-core.js';
|
||||
import { HexFormatter } from './format-hex.js';
|
||||
import { OpenSSLKdf } from './cipher-core.js';
|
||||
import { MD5 } from './md5.js';
|
||||
import { HmacMD5 } from './md5.js';
|
||||
import { SHA1 } from './sha1.js';
|
||||
import { HmacSHA1 } from './sha1.js';
|
||||
import { SHA224 } from './sha224.js';
|
||||
import { HmacSHA224 } from './sha224.js';
|
||||
import { SHA256 } from './sha256.js';
|
||||
import { HmacSHA256 } from './sha256.js';
|
||||
import { SHA384 } from './sha384.js';
|
||||
import { HmacSHA384 } from './sha384.js';
|
||||
import { SHA512 } from './sha512.js';
|
||||
import { HmacSHA512 } from './sha512.js';
|
||||
import { SHA3 } from './sha3.js';
|
||||
import { HmacSHA3 } from './sha3.js';
|
||||
import { RIPEMD160 } from './ripemd160.js';
|
||||
import { HmacRIPEMD160 } from './ripemd160.js';
|
||||
import { PBKDF2 } from './pbkdf2.js';
|
||||
import { EvpKDF } from './evpkdf.js';
|
||||
import { AES } from './aes.js';
|
||||
import { DES } from './tripledes.js';
|
||||
import { TripleDES } from './tripledes.js';
|
||||
import { Rabbit } from './rabbit.js';
|
||||
import { RabbitLegacy } from './rabbit-legacy.js';
|
||||
import { RC4 } from './rc4.js';
|
||||
import { RC4Drop } from './rc4.js';
|
||||
import { Blowfish } from './blowfish.js';
|
||||
@@ -0,0 +1,180 @@
|
||||
import {
|
||||
Base,
|
||||
WordArray,
|
||||
Hex,
|
||||
Latin1,
|
||||
Utf8,
|
||||
BufferedBlockAlgorithm,
|
||||
Hasher,
|
||||
} from './core.js';
|
||||
import {
|
||||
X64Word,
|
||||
X64WordArray,
|
||||
} from './x64-core.js';
|
||||
import {
|
||||
Cipher,
|
||||
StreamCipher,
|
||||
BlockCipherMode,
|
||||
CBC,
|
||||
Pkcs7,
|
||||
BlockCipher,
|
||||
CipherParams,
|
||||
OpenSSLFormatter,
|
||||
SerializableCipher,
|
||||
OpenSSLKdf,
|
||||
PasswordBasedCipher,
|
||||
} from './cipher-core.js';
|
||||
|
||||
import { Utf16, Utf16BE, Utf16LE } from './enc-utf16.js';
|
||||
import { Base64 } from './enc-base64.js';
|
||||
import { Base64url } from './enc-base64url.js';
|
||||
import { HMAC } from './hmac.js';
|
||||
import { MD5Algo, MD5, HmacMD5 } from './md5.js';
|
||||
import { SHA1Algo, SHA1, HmacSHA1 } from './sha1.js';
|
||||
import { SHA224Algo, SHA224, HmacSHA224 } from './sha224.js';
|
||||
import { SHA256Algo, SHA256, HmacSHA256 } from './sha256.js';
|
||||
import { SHA384Algo, SHA384, HmacSHA384 } from './sha384.js';
|
||||
import { SHA512Algo, SHA512, HmacSHA512 } from './sha512.js';
|
||||
import { SHA3Algo, SHA3, HmacSHA3 } from './sha3.js';
|
||||
import { RIPEMD160Algo, RIPEMD160, HmacRIPEMD160 } from './ripemd160.js';
|
||||
import { PBKDF2Algo, PBKDF2 } from './pbkdf2.js';
|
||||
import { EvpKDFAlgo, EvpKDF } from './evpkdf.js';
|
||||
import { AESAlgo, AES } from './aes.js';
|
||||
import {
|
||||
DESAlgo,
|
||||
DES,
|
||||
TripleDESAlgo,
|
||||
TripleDES,
|
||||
} from './tripledes.js';
|
||||
import { RabbitAlgo, Rabbit } from './rabbit.js';
|
||||
import { RabbitLegacyAlgo, RabbitLegacy } from './rabbit-legacy.js';
|
||||
import {
|
||||
RC4Algo,
|
||||
RC4,
|
||||
RC4DropAlgo,
|
||||
RC4Drop,
|
||||
} from './rc4.js';
|
||||
import { BlowfishAlgo, Blowfish } from './blowfish.js';
|
||||
import { CFB } from './mode-cfb.js';
|
||||
import { CTR } from './mode-ctr.js';
|
||||
import { CTRGladman } from './mode-ctr-gladman.js';
|
||||
import { ECB } from './mode-ecb.js';
|
||||
import { OFB } from './mode-ofb.js';
|
||||
import { AnsiX923 } from './pad-ansix923.js';
|
||||
import { Iso10126 } from './pad-iso10126.js';
|
||||
import { Iso97971 } from './pad-iso97971.js';
|
||||
import { NoPadding } from './pad-nopadding.js';
|
||||
import { ZeroPadding } from './pad-zeropadding.js';
|
||||
import { HexFormatter } from './format-hex.js';
|
||||
|
||||
export default {
|
||||
lib: {
|
||||
Base,
|
||||
WordArray,
|
||||
BufferedBlockAlgorithm,
|
||||
Hasher,
|
||||
Cipher,
|
||||
StreamCipher,
|
||||
BlockCipherMode,
|
||||
BlockCipher,
|
||||
CipherParams,
|
||||
SerializableCipher,
|
||||
PasswordBasedCipher,
|
||||
},
|
||||
|
||||
x64: {
|
||||
Word: X64Word,
|
||||
WordArray: X64WordArray,
|
||||
},
|
||||
|
||||
enc: {
|
||||
Hex,
|
||||
Latin1,
|
||||
Utf8,
|
||||
Utf16,
|
||||
Utf16BE,
|
||||
Utf16LE,
|
||||
Base64,
|
||||
Base64url,
|
||||
},
|
||||
|
||||
algo: {
|
||||
HMAC,
|
||||
MD5: MD5Algo,
|
||||
SHA1: SHA1Algo,
|
||||
SHA224: SHA224Algo,
|
||||
SHA256: SHA256Algo,
|
||||
SHA384: SHA384Algo,
|
||||
SHA512: SHA512Algo,
|
||||
SHA3: SHA3Algo,
|
||||
RIPEMD160: RIPEMD160Algo,
|
||||
|
||||
PBKDF2: PBKDF2Algo,
|
||||
EvpKDF: EvpKDFAlgo,
|
||||
|
||||
AES: AESAlgo,
|
||||
DES: DESAlgo,
|
||||
TripleDES: TripleDESAlgo,
|
||||
Rabbit: RabbitAlgo,
|
||||
RabbitLegacy: RabbitLegacyAlgo,
|
||||
RC4: RC4Algo,
|
||||
RC4Drop: RC4DropAlgo,
|
||||
Blowfish: BlowfishAlgo,
|
||||
},
|
||||
|
||||
mode: {
|
||||
CBC,
|
||||
CFB,
|
||||
CTR,
|
||||
CTRGladman,
|
||||
ECB,
|
||||
OFB,
|
||||
},
|
||||
|
||||
pad: {
|
||||
Pkcs7,
|
||||
AnsiX923,
|
||||
Iso10126,
|
||||
Iso97971,
|
||||
NoPadding,
|
||||
ZeroPadding,
|
||||
},
|
||||
|
||||
format: {
|
||||
OpenSSL: OpenSSLFormatter,
|
||||
Hex: HexFormatter,
|
||||
},
|
||||
|
||||
kdf: {
|
||||
OpenSSL: OpenSSLKdf,
|
||||
},
|
||||
|
||||
MD5,
|
||||
HmacMD5,
|
||||
SHA1,
|
||||
HmacSHA1,
|
||||
SHA224,
|
||||
HmacSHA224,
|
||||
SHA256,
|
||||
HmacSHA256,
|
||||
SHA384,
|
||||
HmacSHA384,
|
||||
SHA512,
|
||||
HmacSHA512,
|
||||
SHA3,
|
||||
HmacSHA3,
|
||||
RIPEMD160,
|
||||
HmacRIPEMD160,
|
||||
|
||||
PBKDF2,
|
||||
EvpKDF,
|
||||
|
||||
AES,
|
||||
DES,
|
||||
TripleDES,
|
||||
Rabbit,
|
||||
RabbitLegacy,
|
||||
RC4,
|
||||
RC4Drop,
|
||||
Blowfish,
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* MD5 hash algorithm.
|
||||
*/
|
||||
export class MD5Algo extends Hasher {}
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.MD5('message');
|
||||
* var hash = CryptoJS.MD5(wordArray);
|
||||
*/
|
||||
export const MD5: HashFn;
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacMD5(message, key);
|
||||
*/
|
||||
export const HmacMD5: HMACHashFn;
|
||||
import { Hasher } from './core.js';
|
||||
import { HashFn } from './core.js';
|
||||
import { HMACHashFn } from './core.js';
|
||||
@@ -0,0 +1,247 @@
|
||||
import {
|
||||
WordArray,
|
||||
Hasher,
|
||||
} from './core.js';
|
||||
|
||||
// Constants table
|
||||
const T = [];
|
||||
|
||||
// Compute constants
|
||||
for (let i = 0; i < 64; i += 1) {
|
||||
T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
|
||||
}
|
||||
|
||||
const FF = (a, b, c, d, x, s, t) => {
|
||||
const n = a + ((b & c) | (~b & d)) + x + t;
|
||||
return ((n << s) | (n >>> (32 - s))) + b;
|
||||
};
|
||||
|
||||
const GG = (a, b, c, d, x, s, t) => {
|
||||
const n = a + ((b & d) | (c & ~d)) + x + t;
|
||||
return ((n << s) | (n >>> (32 - s))) + b;
|
||||
};
|
||||
|
||||
const HH = (a, b, c, d, x, s, t) => {
|
||||
const n = a + (b ^ c ^ d) + x + t;
|
||||
return ((n << s) | (n >>> (32 - s))) + b;
|
||||
};
|
||||
|
||||
const II = (a, b, c, d, x, s, t) => {
|
||||
const n = a + (c ^ (b | ~d)) + x + t;
|
||||
return ((n << s) | (n >>> (32 - s))) + b;
|
||||
};
|
||||
|
||||
/**
|
||||
* MD5 hash algorithm.
|
||||
*/
|
||||
export class MD5Algo extends Hasher {
|
||||
_doReset() {
|
||||
this._hash = new WordArray([
|
||||
0x67452301,
|
||||
0xefcdab89,
|
||||
0x98badcfe,
|
||||
0x10325476,
|
||||
]);
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
const _M = M;
|
||||
|
||||
// Swap endian
|
||||
for (let i = 0; i < 16; i += 1) {
|
||||
// Shortcuts
|
||||
const offset_i = offset + i;
|
||||
const M_offset_i = M[offset_i];
|
||||
|
||||
_M[offset_i] = (
|
||||
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff)
|
||||
| (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
|
||||
);
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
const H = this._hash.words;
|
||||
|
||||
const M_offset_0 = _M[offset + 0];
|
||||
const M_offset_1 = _M[offset + 1];
|
||||
const M_offset_2 = _M[offset + 2];
|
||||
const M_offset_3 = _M[offset + 3];
|
||||
const M_offset_4 = _M[offset + 4];
|
||||
const M_offset_5 = _M[offset + 5];
|
||||
const M_offset_6 = _M[offset + 6];
|
||||
const M_offset_7 = _M[offset + 7];
|
||||
const M_offset_8 = _M[offset + 8];
|
||||
const M_offset_9 = _M[offset + 9];
|
||||
const M_offset_10 = _M[offset + 10];
|
||||
const M_offset_11 = _M[offset + 11];
|
||||
const M_offset_12 = _M[offset + 12];
|
||||
const M_offset_13 = _M[offset + 13];
|
||||
const M_offset_14 = _M[offset + 14];
|
||||
const M_offset_15 = _M[offset + 15];
|
||||
|
||||
// Working varialbes
|
||||
let a = H[0];
|
||||
let b = H[1];
|
||||
let c = H[2];
|
||||
let d = H[3];
|
||||
|
||||
// Computation
|
||||
a = FF(a, b, c, d, M_offset_0, 7, T[0]);
|
||||
d = FF(d, a, b, c, M_offset_1, 12, T[1]);
|
||||
c = FF(c, d, a, b, M_offset_2, 17, T[2]);
|
||||
b = FF(b, c, d, a, M_offset_3, 22, T[3]);
|
||||
a = FF(a, b, c, d, M_offset_4, 7, T[4]);
|
||||
d = FF(d, a, b, c, M_offset_5, 12, T[5]);
|
||||
c = FF(c, d, a, b, M_offset_6, 17, T[6]);
|
||||
b = FF(b, c, d, a, M_offset_7, 22, T[7]);
|
||||
a = FF(a, b, c, d, M_offset_8, 7, T[8]);
|
||||
d = FF(d, a, b, c, M_offset_9, 12, T[9]);
|
||||
c = FF(c, d, a, b, M_offset_10, 17, T[10]);
|
||||
b = FF(b, c, d, a, M_offset_11, 22, T[11]);
|
||||
a = FF(a, b, c, d, M_offset_12, 7, T[12]);
|
||||
d = FF(d, a, b, c, M_offset_13, 12, T[13]);
|
||||
c = FF(c, d, a, b, M_offset_14, 17, T[14]);
|
||||
b = FF(b, c, d, a, M_offset_15, 22, T[15]);
|
||||
|
||||
a = GG(a, b, c, d, M_offset_1, 5, T[16]);
|
||||
d = GG(d, a, b, c, M_offset_6, 9, T[17]);
|
||||
c = GG(c, d, a, b, M_offset_11, 14, T[18]);
|
||||
b = GG(b, c, d, a, M_offset_0, 20, T[19]);
|
||||
a = GG(a, b, c, d, M_offset_5, 5, T[20]);
|
||||
d = GG(d, a, b, c, M_offset_10, 9, T[21]);
|
||||
c = GG(c, d, a, b, M_offset_15, 14, T[22]);
|
||||
b = GG(b, c, d, a, M_offset_4, 20, T[23]);
|
||||
a = GG(a, b, c, d, M_offset_9, 5, T[24]);
|
||||
d = GG(d, a, b, c, M_offset_14, 9, T[25]);
|
||||
c = GG(c, d, a, b, M_offset_3, 14, T[26]);
|
||||
b = GG(b, c, d, a, M_offset_8, 20, T[27]);
|
||||
a = GG(a, b, c, d, M_offset_13, 5, T[28]);
|
||||
d = GG(d, a, b, c, M_offset_2, 9, T[29]);
|
||||
c = GG(c, d, a, b, M_offset_7, 14, T[30]);
|
||||
b = GG(b, c, d, a, M_offset_12, 20, T[31]);
|
||||
|
||||
a = HH(a, b, c, d, M_offset_5, 4, T[32]);
|
||||
d = HH(d, a, b, c, M_offset_8, 11, T[33]);
|
||||
c = HH(c, d, a, b, M_offset_11, 16, T[34]);
|
||||
b = HH(b, c, d, a, M_offset_14, 23, T[35]);
|
||||
a = HH(a, b, c, d, M_offset_1, 4, T[36]);
|
||||
d = HH(d, a, b, c, M_offset_4, 11, T[37]);
|
||||
c = HH(c, d, a, b, M_offset_7, 16, T[38]);
|
||||
b = HH(b, c, d, a, M_offset_10, 23, T[39]);
|
||||
a = HH(a, b, c, d, M_offset_13, 4, T[40]);
|
||||
d = HH(d, a, b, c, M_offset_0, 11, T[41]);
|
||||
c = HH(c, d, a, b, M_offset_3, 16, T[42]);
|
||||
b = HH(b, c, d, a, M_offset_6, 23, T[43]);
|
||||
a = HH(a, b, c, d, M_offset_9, 4, T[44]);
|
||||
d = HH(d, a, b, c, M_offset_12, 11, T[45]);
|
||||
c = HH(c, d, a, b, M_offset_15, 16, T[46]);
|
||||
b = HH(b, c, d, a, M_offset_2, 23, T[47]);
|
||||
|
||||
a = II(a, b, c, d, M_offset_0, 6, T[48]);
|
||||
d = II(d, a, b, c, M_offset_7, 10, T[49]);
|
||||
c = II(c, d, a, b, M_offset_14, 15, T[50]);
|
||||
b = II(b, c, d, a, M_offset_5, 21, T[51]);
|
||||
a = II(a, b, c, d, M_offset_12, 6, T[52]);
|
||||
d = II(d, a, b, c, M_offset_3, 10, T[53]);
|
||||
c = II(c, d, a, b, M_offset_10, 15, T[54]);
|
||||
b = II(b, c, d, a, M_offset_1, 21, T[55]);
|
||||
a = II(a, b, c, d, M_offset_8, 6, T[56]);
|
||||
d = II(d, a, b, c, M_offset_15, 10, T[57]);
|
||||
c = II(c, d, a, b, M_offset_6, 15, T[58]);
|
||||
b = II(b, c, d, a, M_offset_13, 21, T[59]);
|
||||
a = II(a, b, c, d, M_offset_4, 6, T[60]);
|
||||
d = II(d, a, b, c, M_offset_11, 10, T[61]);
|
||||
c = II(c, d, a, b, M_offset_2, 15, T[62]);
|
||||
b = II(b, c, d, a, M_offset_9, 21, T[63]);
|
||||
|
||||
// Intermediate hash value
|
||||
H[0] = (H[0] + a) | 0;
|
||||
H[1] = (H[1] + b) | 0;
|
||||
H[2] = (H[2] + c) | 0;
|
||||
H[3] = (H[3] + d) | 0;
|
||||
}
|
||||
/* eslint-ensable no-param-reassign */
|
||||
|
||||
_doFinalize() {
|
||||
// Shortcuts
|
||||
const data = this._data;
|
||||
const dataWords = data.words;
|
||||
|
||||
const nBitsTotal = this._nDataBytes * 8;
|
||||
const nBitsLeft = data.sigBytes * 8;
|
||||
|
||||
// Add padding
|
||||
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32));
|
||||
|
||||
const nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
|
||||
const nBitsTotalL = nBitsTotal;
|
||||
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
|
||||
(((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff)
|
||||
| (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)
|
||||
);
|
||||
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
|
||||
(((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff)
|
||||
| (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)
|
||||
);
|
||||
|
||||
data.sigBytes = (dataWords.length + 1) * 4;
|
||||
|
||||
// Hash final blocks
|
||||
this._process();
|
||||
|
||||
// Shortcuts
|
||||
const hash = this._hash;
|
||||
const H = hash.words;
|
||||
|
||||
// Swap endian
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
// Shortcut
|
||||
const H_i = H[i];
|
||||
|
||||
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff)
|
||||
| (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
|
||||
}
|
||||
|
||||
// Return final computed hash
|
||||
return hash;
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
clone._hash = this._hash.clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.MD5('message');
|
||||
* var hash = CryptoJS.MD5(wordArray);
|
||||
*/
|
||||
export const MD5 = Hasher._createHelper(MD5Algo);
|
||||
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacMD5(message, key);
|
||||
*/
|
||||
export const HmacMD5 = Hasher._createHmacHelper(MD5Algo);
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Cipher Feedback block mode.
|
||||
*/
|
||||
export class CFB extends BlockCipherMode {
|
||||
}
|
||||
import { BlockCipherMode } from './cipher-core.js';
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
BlockCipherMode,
|
||||
} from './cipher-core.js';
|
||||
|
||||
function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) {
|
||||
const _words = words;
|
||||
let keystream;
|
||||
|
||||
// Shortcut
|
||||
const iv = this._iv;
|
||||
|
||||
// Generate keystream
|
||||
if (iv) {
|
||||
keystream = iv.slice(0);
|
||||
|
||||
// Remove IV for subsequent blocks
|
||||
this._iv = undefined;
|
||||
} else {
|
||||
keystream = this._prevBlock;
|
||||
}
|
||||
cipher.encryptBlock(keystream, 0);
|
||||
|
||||
// Encrypt
|
||||
for (let i = 0; i < blockSize; i += 1) {
|
||||
_words[offset + i] ^= keystream[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cipher Feedback block mode.
|
||||
*/
|
||||
export class CFB extends BlockCipherMode {
|
||||
}
|
||||
CFB.Encryptor = class extends CFB {
|
||||
processBlock(words, offset) {
|
||||
// Shortcuts
|
||||
const cipher = this._cipher;
|
||||
const { blockSize } = cipher;
|
||||
|
||||
generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher);
|
||||
|
||||
// Remember this block to use with next block
|
||||
this._prevBlock = words.slice(offset, offset + blockSize);
|
||||
}
|
||||
};
|
||||
CFB.Decryptor = class extends CFB {
|
||||
processBlock(words, offset) {
|
||||
// Shortcuts
|
||||
const cipher = this._cipher;
|
||||
const { blockSize } = cipher;
|
||||
|
||||
// Remember this block to use with next block
|
||||
const thisBlock = words.slice(offset, offset + blockSize);
|
||||
|
||||
generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher);
|
||||
|
||||
// This block becomes the previous block
|
||||
this._prevBlock = thisBlock;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
/** @preserve
|
||||
* Counter block mode compatible with Dr Brian Gladman fileenc.c
|
||||
* derived from CryptoJS.mode.CTR
|
||||
* Jan Hruby jhruby.web@gmail.com
|
||||
*/
|
||||
export class CTRGladman extends BlockCipherMode {
|
||||
}
|
||||
import { BlockCipherMode } from './cipher-core.js';
|
||||
@@ -0,0 +1,87 @@
|
||||
import {
|
||||
BlockCipherMode,
|
||||
} from './cipher-core.js';
|
||||
|
||||
const incWord = (word) => {
|
||||
let _word = word;
|
||||
|
||||
if (((word >> 24) & 0xff) === 0xff) { // overflow
|
||||
let b1 = (word >> 16) & 0xff;
|
||||
let b2 = (word >> 8) & 0xff;
|
||||
let b3 = word & 0xff;
|
||||
|
||||
if (b1 === 0xff) { // overflow b1
|
||||
b1 = 0;
|
||||
if (b2 === 0xff) {
|
||||
b2 = 0;
|
||||
if (b3 === 0xff) {
|
||||
b3 = 0;
|
||||
} else {
|
||||
b3 += 1;
|
||||
}
|
||||
} else {
|
||||
b2 += 1;
|
||||
}
|
||||
} else {
|
||||
b1 += 1;
|
||||
}
|
||||
|
||||
_word = 0;
|
||||
_word += (b1 << 16);
|
||||
_word += (b2 << 8);
|
||||
_word += b3;
|
||||
} else {
|
||||
_word += (0x01 << 24);
|
||||
}
|
||||
return _word;
|
||||
};
|
||||
|
||||
const incCounter = (counter) => {
|
||||
const _counter = counter;
|
||||
_counter[0] = incWord(_counter[0]);
|
||||
|
||||
if (_counter[0] === 0) {
|
||||
// encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8
|
||||
_counter[1] = incWord(_counter[1]);
|
||||
}
|
||||
return _counter;
|
||||
};
|
||||
|
||||
/** @preserve
|
||||
* Counter block mode compatible with Dr Brian Gladman fileenc.c
|
||||
* derived from CryptoJS.mode.CTR
|
||||
* Jan Hruby jhruby.web@gmail.com
|
||||
*/
|
||||
export class CTRGladman extends BlockCipherMode {
|
||||
}
|
||||
CTRGladman.Encryptor = class extends CTRGladman {
|
||||
processBlock(words, offset) {
|
||||
const _words = words;
|
||||
|
||||
// Shortcuts
|
||||
const cipher = this._cipher;
|
||||
const { blockSize } = cipher;
|
||||
const iv = this._iv;
|
||||
let counter = this._counter;
|
||||
|
||||
// Generate keystream
|
||||
if (iv) {
|
||||
this._counter = iv.slice(0);
|
||||
counter = this._counter;
|
||||
|
||||
// Remove IV for subsequent blocks
|
||||
this._iv = undefined;
|
||||
}
|
||||
|
||||
incCounter(counter);
|
||||
|
||||
const keystream = counter.slice(0);
|
||||
cipher.encryptBlock(keystream, 0);
|
||||
|
||||
// Encrypt
|
||||
for (let i = 0; i < blockSize; i += 1) {
|
||||
_words[offset + i] ^= keystream[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
CTRGladman.Decryptor = CTRGladman.Encryptor;
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Counter block mode.
|
||||
*/
|
||||
export class CTR extends BlockCipherMode {
|
||||
}
|
||||
import { BlockCipherMode } from './cipher-core.js';
|
||||
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
BlockCipherMode,
|
||||
} from './cipher-core.js';
|
||||
|
||||
/**
|
||||
* Counter block mode.
|
||||
*/
|
||||
export class CTR extends BlockCipherMode {
|
||||
}
|
||||
CTR.Encryptor = class extends CTR {
|
||||
processBlock(words, offset) {
|
||||
const _words = words;
|
||||
|
||||
// Shortcuts
|
||||
const cipher = this._cipher;
|
||||
const { blockSize } = cipher;
|
||||
const iv = this._iv;
|
||||
let counter = this._counter;
|
||||
|
||||
// Generate keystream
|
||||
if (iv) {
|
||||
this._counter = iv.slice(0);
|
||||
counter = this._counter;
|
||||
|
||||
// Remove IV for subsequent blocks
|
||||
this._iv = undefined;
|
||||
}
|
||||
const keystream = counter.slice(0);
|
||||
cipher.encryptBlock(keystream, 0);
|
||||
|
||||
// Increment counter
|
||||
counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0;
|
||||
|
||||
// Encrypt
|
||||
for (let i = 0; i < blockSize; i += 1) {
|
||||
_words[offset + i] ^= keystream[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
CTR.Decryptor = CTR.Encryptor;
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Electronic Codebook block mode.
|
||||
*/
|
||||
export class ECB extends BlockCipherMode {
|
||||
}
|
||||
import { BlockCipherMode } from './cipher-core.js';
|
||||
@@ -0,0 +1,19 @@
|
||||
import {
|
||||
BlockCipherMode,
|
||||
} from './cipher-core.js';
|
||||
|
||||
/**
|
||||
* Electronic Codebook block mode.
|
||||
*/
|
||||
export class ECB extends BlockCipherMode {
|
||||
}
|
||||
ECB.Encryptor = class extends ECB {
|
||||
processBlock(words, offset) {
|
||||
this._cipher.encryptBlock(words, offset);
|
||||
}
|
||||
};
|
||||
ECB.Decryptor = class extends ECB {
|
||||
processBlock(words, offset) {
|
||||
this._cipher.decryptBlock(words, offset);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Output Feedback block mode.
|
||||
*/
|
||||
export class OFB extends BlockCipherMode {
|
||||
}
|
||||
import { BlockCipherMode } from './cipher-core.js';
|
||||
@@ -0,0 +1,36 @@
|
||||
import {
|
||||
BlockCipherMode,
|
||||
} from './cipher-core.js';
|
||||
|
||||
/**
|
||||
* Output Feedback block mode.
|
||||
*/
|
||||
export class OFB extends BlockCipherMode {
|
||||
}
|
||||
OFB.Encryptor = class extends OFB {
|
||||
processBlock(words, offset) {
|
||||
const _words = words;
|
||||
|
||||
// Shortcuts
|
||||
const cipher = this._cipher;
|
||||
const { blockSize } = cipher;
|
||||
const iv = this._iv;
|
||||
let keystream = this._keystream;
|
||||
|
||||
// Generate keystream
|
||||
if (iv) {
|
||||
this._keystream = iv.slice(0);
|
||||
keystream = this._keystream;
|
||||
|
||||
// Remove IV for subsequent blocks
|
||||
this._iv = undefined;
|
||||
}
|
||||
cipher.encryptBlock(keystream, 0);
|
||||
|
||||
// Encrypt
|
||||
for (let i = 0; i < blockSize; i += 1) {
|
||||
_words[offset + i] ^= keystream[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
OFB.Decryptor = OFB.Encryptor;
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* ANSI X.923 padding strategy.
|
||||
*/
|
||||
export const AnsiX923: Padding;
|
||||
import { Padding } from './cipher-core';
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* ANSI X.923 padding strategy.
|
||||
*/
|
||||
export const AnsiX923 = {
|
||||
pad(data, blockSize) {
|
||||
const _data = data;
|
||||
|
||||
// Shortcuts
|
||||
const dataSigBytes = _data.sigBytes;
|
||||
const blockSizeBytes = blockSize * 4;
|
||||
|
||||
// Count padding bytes
|
||||
const nPaddingBytes = blockSizeBytes - (dataSigBytes % blockSizeBytes);
|
||||
|
||||
// Compute last byte position
|
||||
const lastBytePos = dataSigBytes + nPaddingBytes - 1;
|
||||
|
||||
// Pad
|
||||
_data.clamp();
|
||||
_data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8);
|
||||
_data.sigBytes += nPaddingBytes;
|
||||
},
|
||||
|
||||
unpad(data) {
|
||||
const _data = data;
|
||||
|
||||
// Get number of padding bytes from last byte
|
||||
const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff;
|
||||
|
||||
// Remove padding
|
||||
_data.sigBytes -= nPaddingBytes;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* ISO 10126 padding strategy.
|
||||
*/
|
||||
export const Iso10126: Padding;
|
||||
import { Padding } from './cipher-core';
|
||||
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
|
||||
/**
|
||||
* ISO 10126 padding strategy.
|
||||
*/
|
||||
export const Iso10126 = {
|
||||
pad(data, blockSize) {
|
||||
// Shortcut
|
||||
const blockSizeBytes = blockSize * 4;
|
||||
|
||||
// Count padding bytes
|
||||
const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes);
|
||||
|
||||
// Pad
|
||||
data
|
||||
.concat(WordArray.random(nPaddingBytes - 1))
|
||||
.concat(WordArray.create([nPaddingBytes << 24], 1));
|
||||
},
|
||||
|
||||
unpad(data) {
|
||||
const _data = data;
|
||||
// Get number of padding bytes from last byte
|
||||
const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff;
|
||||
|
||||
// Remove padding
|
||||
_data.sigBytes -= nPaddingBytes;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* ISO/IEC 9797-1 Padding Method 2.
|
||||
*/
|
||||
export const Iso97971: Padding;
|
||||
import { Padding } from './cipher-core';
|
||||
@@ -0,0 +1,29 @@
|
||||
import {
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
import {
|
||||
ZeroPadding,
|
||||
} from './pad-zeropadding.js';
|
||||
|
||||
/**
|
||||
* ISO/IEC 9797-1 Padding Method 2.
|
||||
*/
|
||||
export const Iso97971 = {
|
||||
pad(data, blockSize) {
|
||||
// Add 0x80 byte
|
||||
data.concat(WordArray.create([0x80000000], 1));
|
||||
|
||||
// Zero pad the rest
|
||||
ZeroPadding.pad(data, blockSize);
|
||||
},
|
||||
|
||||
unpad(data) {
|
||||
const _data = data;
|
||||
|
||||
// Remove zero padding
|
||||
ZeroPadding.unpad(_data);
|
||||
|
||||
// Remove one more byte -- the 0x80 byte
|
||||
_data.sigBytes -= 1;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* A noop padding strategy.
|
||||
*/
|
||||
export const NoPadding: Padding;
|
||||
import { Padding } from './cipher-core';
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* A noop padding strategy.
|
||||
*/
|
||||
export const NoPadding = {
|
||||
pad() {
|
||||
},
|
||||
|
||||
unpad() {
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Zero padding strategy.
|
||||
*/
|
||||
export const ZeroPadding: Padding;
|
||||
import { Padding } from './cipher-core';
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Zero padding strategy.
|
||||
*/
|
||||
export const ZeroPadding = {
|
||||
pad(data, blockSize) {
|
||||
const _data = data;
|
||||
|
||||
// Shortcut
|
||||
const blockSizeBytes = blockSize * 4;
|
||||
|
||||
// Pad
|
||||
_data.clamp();
|
||||
_data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes);
|
||||
},
|
||||
|
||||
unpad(data) {
|
||||
const _data = data;
|
||||
|
||||
// Shortcut
|
||||
const dataWords = _data.words;
|
||||
|
||||
// Unpad
|
||||
for (let i = _data.sigBytes - 1; i >= 0; i -= 1) {
|
||||
if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) {
|
||||
_data.sigBytes = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Password-Based Key Derivation Function 2 algorithm.
|
||||
*/
|
||||
export class PBKDF2Algo extends Base {
|
||||
static create(cfg?: KDFCfg): PBKDF2Algo;
|
||||
constructor(cfg?: KDFCfg);
|
||||
compute(password: WordArray | string, salt: WordArray | string): WordArray;
|
||||
}
|
||||
/**
|
||||
* Computes the Password-Based Key Derivation Function 2.
|
||||
*
|
||||
* @param {WordArray|string} password The password.
|
||||
* @param {WordArray|string} salt A salt.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this computation.
|
||||
*
|
||||
* @return {WordArray} The derived key.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var key = CryptoJS.PBKDF2(password, salt);
|
||||
* var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
|
||||
* var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
|
||||
*/
|
||||
export const PBKDF2: KDFFn;
|
||||
import { Base } from './core.js';
|
||||
import { WordArray } from './core.js';
|
||||
import { KDFCfg } from './core.js';
|
||||
import { KDFFn } from './core.js';
|
||||
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
Base,
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
import { SHA256Algo } from './sha256.js';
|
||||
import { HMAC } from './hmac.js';
|
||||
|
||||
/**
|
||||
* Password-Based Key Derivation Function 2 algorithm.
|
||||
*/
|
||||
export class PBKDF2Algo extends Base {
|
||||
/**
|
||||
* Initializes a newly created key derivation function.
|
||||
*
|
||||
* @param {Object} cfg (Optional) The configuration options to use for the derivation.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const kdf = CryptoJS.algo.PBKDF2.create();
|
||||
* const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
|
||||
* const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 });
|
||||
*/
|
||||
constructor(cfg) {
|
||||
super();
|
||||
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* The default `hasher` and `interations` is different from CryptoJs to enhance security:
|
||||
* https://github.com/entronad/crypto-es/security/advisories/GHSA-mpj8-q39x-wq5h
|
||||
*
|
||||
* @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
|
||||
* @property {Hasher} hasher The hasher to use. Default: SHA256
|
||||
* @property {number} iterations The number of iterations to perform. Default: 250000
|
||||
*/
|
||||
this.cfg = Object.assign(
|
||||
new Base(),
|
||||
{
|
||||
keySize: 128 / 32,
|
||||
hasher: SHA256Algo,
|
||||
iterations: 250000,
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the Password-Based Key Derivation Function 2.
|
||||
*
|
||||
* @param {WordArray|string} password The password.
|
||||
* @param {WordArray|string} salt A salt.
|
||||
*
|
||||
* @return {WordArray} The derived key.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* const key = kdf.compute(password, salt);
|
||||
*/
|
||||
compute(password, salt) {
|
||||
// Shortcut
|
||||
const { cfg } = this;
|
||||
|
||||
// Init HMAC
|
||||
const hmac = HMAC.create(cfg.hasher, password);
|
||||
|
||||
// Initial values
|
||||
const derivedKey = WordArray.create();
|
||||
const blockIndex = WordArray.create([0x00000001]);
|
||||
|
||||
// Shortcuts
|
||||
const derivedKeyWords = derivedKey.words;
|
||||
const blockIndexWords = blockIndex.words;
|
||||
const { keySize, iterations } = cfg;
|
||||
|
||||
// Generate key
|
||||
while (derivedKeyWords.length < keySize) {
|
||||
const block = hmac.update(salt).finalize(blockIndex);
|
||||
hmac.reset();
|
||||
|
||||
// Shortcuts
|
||||
const blockWords = block.words;
|
||||
const blockWordsLength = blockWords.length;
|
||||
|
||||
// Iterations
|
||||
let intermediate = block;
|
||||
for (let i = 1; i < iterations; i += 1) {
|
||||
intermediate = hmac.finalize(intermediate);
|
||||
hmac.reset();
|
||||
|
||||
// Shortcut
|
||||
const intermediateWords = intermediate.words;
|
||||
|
||||
// XOR intermediate with block
|
||||
for (let j = 0; j < blockWordsLength; j += 1) {
|
||||
blockWords[j] ^= intermediateWords[j];
|
||||
}
|
||||
}
|
||||
|
||||
derivedKey.concat(block);
|
||||
blockIndexWords[0] += 1;
|
||||
}
|
||||
derivedKey.sigBytes = keySize * 4;
|
||||
|
||||
return derivedKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the Password-Based Key Derivation Function 2.
|
||||
*
|
||||
* @param {WordArray|string} password The password.
|
||||
* @param {WordArray|string} salt A salt.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this computation.
|
||||
*
|
||||
* @return {WordArray} The derived key.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var key = CryptoJS.PBKDF2(password, salt);
|
||||
* var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
|
||||
* var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
|
||||
*/
|
||||
export const PBKDF2 = (password, salt, cfg) => PBKDF2Algo.create(cfg).compute(password, salt);
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Rabbit stream cipher algorithm.
|
||||
*
|
||||
* This is a legacy version that neglected to convert the key to little-endian.
|
||||
* This error doesn't affect the cipher's security,
|
||||
* but it does affect its compatibility with other implementations.
|
||||
*/
|
||||
export class RabbitLegacyAlgo extends StreamCipher {
|
||||
}
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const RabbitLegacy: CipherObj;
|
||||
import { CipherObj } from './cipher-core.js';
|
||||
import { StreamCipher } from './cipher-core.js';
|
||||
@@ -0,0 +1,175 @@
|
||||
import {
|
||||
StreamCipher,
|
||||
} from './cipher-core.js';
|
||||
|
||||
// Reusable objects
|
||||
const S = [];
|
||||
const C_ = [];
|
||||
const G = [];
|
||||
|
||||
function nextState() {
|
||||
// Shortcuts
|
||||
const X = this._X;
|
||||
const C = this._C;
|
||||
|
||||
// Save old counter values
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
C_[i] = C[i];
|
||||
}
|
||||
|
||||
// Calculate new counter values
|
||||
C[0] = (C[0] + 0x4d34d34d + this._b) | 0;
|
||||
C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0;
|
||||
C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0;
|
||||
C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0;
|
||||
C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0;
|
||||
C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0;
|
||||
C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0;
|
||||
C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0;
|
||||
this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0;
|
||||
|
||||
// Calculate the g-values
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
const gx = X[i] + C[i];
|
||||
|
||||
// Construct high and low argument for squaring
|
||||
const ga = gx & 0xffff;
|
||||
const gb = gx >>> 16;
|
||||
|
||||
// Calculate high and low result of squaring
|
||||
const gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb;
|
||||
const gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0);
|
||||
|
||||
// High XOR low
|
||||
G[i] = gh ^ gl;
|
||||
}
|
||||
|
||||
// Calculate new state values
|
||||
X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0;
|
||||
X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0;
|
||||
X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0;
|
||||
X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0;
|
||||
X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0;
|
||||
X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0;
|
||||
X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0;
|
||||
X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rabbit stream cipher algorithm.
|
||||
*
|
||||
* This is a legacy version that neglected to convert the key to little-endian.
|
||||
* This error doesn't affect the cipher's security,
|
||||
* but it does affect its compatibility with other implementations.
|
||||
*/
|
||||
export class RabbitLegacyAlgo extends StreamCipher {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
this.blockSize = 128 / 32;
|
||||
this.ivSize = 64 / 32;
|
||||
}
|
||||
|
||||
_doReset() {
|
||||
// Shortcuts
|
||||
const K = this._key.words;
|
||||
const { iv } = this.cfg;
|
||||
|
||||
// Generate initial state values
|
||||
this._X = [
|
||||
K[0], (K[3] << 16) | (K[2] >>> 16),
|
||||
K[1], (K[0] << 16) | (K[3] >>> 16),
|
||||
K[2], (K[1] << 16) | (K[0] >>> 16),
|
||||
K[3], (K[2] << 16) | (K[1] >>> 16),
|
||||
];
|
||||
const X = this._X;
|
||||
|
||||
// Generate initial counter values
|
||||
this._C = [
|
||||
(K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff),
|
||||
(K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff),
|
||||
(K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff),
|
||||
(K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff),
|
||||
];
|
||||
const C = this._C;
|
||||
|
||||
// Carry bit
|
||||
this._b = 0;
|
||||
|
||||
// Iterate the system four times
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
nextState.call(this);
|
||||
}
|
||||
|
||||
// Modify the counters
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
C[i] ^= X[(i + 4) & 7];
|
||||
}
|
||||
|
||||
// IV setup
|
||||
if (iv) {
|
||||
// Shortcuts
|
||||
const IV = iv.words;
|
||||
const IV_0 = IV[0];
|
||||
const IV_1 = IV[1];
|
||||
|
||||
// Generate four subvectors
|
||||
const i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff)
|
||||
| (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00);
|
||||
const i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff)
|
||||
| (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00);
|
||||
const i1 = (i0 >>> 16) | (i2 & 0xffff0000);
|
||||
const i3 = (i2 << 16) | (i0 & 0x0000ffff);
|
||||
|
||||
// Modify counter values
|
||||
C[0] ^= i0;
|
||||
C[1] ^= i1;
|
||||
C[2] ^= i2;
|
||||
C[3] ^= i3;
|
||||
C[4] ^= i0;
|
||||
C[5] ^= i1;
|
||||
C[6] ^= i2;
|
||||
C[7] ^= i3;
|
||||
|
||||
// Iterate the system four times
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
nextState.call(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
const _M = M;
|
||||
|
||||
// Shortcut
|
||||
const X = this._X;
|
||||
|
||||
// Iterate the system
|
||||
nextState.call(this);
|
||||
|
||||
// Generate four keystream words
|
||||
S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16);
|
||||
S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16);
|
||||
S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16);
|
||||
S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16);
|
||||
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
// Swap endian
|
||||
S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff)
|
||||
| (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00);
|
||||
|
||||
// Encrypt
|
||||
_M[offset + i] ^= S[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const RabbitLegacy = StreamCipher._createHelper(RabbitLegacyAlgo);
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Rabbit stream cipher algorithm
|
||||
*/
|
||||
export class RabbitAlgo extends StreamCipher {
|
||||
}
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const Rabbit: CipherObj;
|
||||
import { CipherObj } from './cipher-core.js';
|
||||
import { StreamCipher } from './cipher-core.js';
|
||||
@@ -0,0 +1,177 @@
|
||||
import {
|
||||
StreamCipher,
|
||||
} from './cipher-core.js';
|
||||
|
||||
// Reusable objects
|
||||
const S = [];
|
||||
const C_ = [];
|
||||
const G = [];
|
||||
|
||||
function nextState() {
|
||||
// Shortcuts
|
||||
const X = this._X;
|
||||
const C = this._C;
|
||||
|
||||
// Save old counter values
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
C_[i] = C[i];
|
||||
}
|
||||
|
||||
// Calculate new counter values
|
||||
C[0] = (C[0] + 0x4d34d34d + this._b) | 0;
|
||||
C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0;
|
||||
C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0;
|
||||
C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0;
|
||||
C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0;
|
||||
C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0;
|
||||
C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0;
|
||||
C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0;
|
||||
this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0;
|
||||
|
||||
// Calculate the g-values
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
const gx = X[i] + C[i];
|
||||
|
||||
// Construct high and low argument for squaring
|
||||
const ga = gx & 0xffff;
|
||||
const gb = gx >>> 16;
|
||||
|
||||
// Calculate high and low result of squaring
|
||||
const gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb;
|
||||
const gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0);
|
||||
|
||||
// High XOR low
|
||||
G[i] = gh ^ gl;
|
||||
}
|
||||
|
||||
// Calculate new state values
|
||||
X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0;
|
||||
X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0;
|
||||
X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0;
|
||||
X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0;
|
||||
X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0;
|
||||
X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0;
|
||||
X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0;
|
||||
X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rabbit stream cipher algorithm
|
||||
*/
|
||||
export class RabbitAlgo extends StreamCipher {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
this.blockSize = 128 / 32;
|
||||
this.ivSize = 64 / 32;
|
||||
}
|
||||
|
||||
_doReset() {
|
||||
// Shortcuts
|
||||
const K = this._key.words;
|
||||
const { iv } = this.cfg;
|
||||
|
||||
// Swap endian
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff)
|
||||
| (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00);
|
||||
}
|
||||
|
||||
// Generate initial state values
|
||||
this._X = [
|
||||
K[0], (K[3] << 16) | (K[2] >>> 16),
|
||||
K[1], (K[0] << 16) | (K[3] >>> 16),
|
||||
K[2], (K[1] << 16) | (K[0] >>> 16),
|
||||
K[3], (K[2] << 16) | (K[1] >>> 16),
|
||||
];
|
||||
const X = this._X;
|
||||
|
||||
// Generate initial counter values
|
||||
this._C = [
|
||||
(K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff),
|
||||
(K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff),
|
||||
(K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff),
|
||||
(K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff),
|
||||
];
|
||||
const C = this._C;
|
||||
|
||||
// Carry bit
|
||||
this._b = 0;
|
||||
|
||||
// Iterate the system four times
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
nextState.call(this);
|
||||
}
|
||||
|
||||
// Modify the counters
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
C[i] ^= X[(i + 4) & 7];
|
||||
}
|
||||
|
||||
// IV setup
|
||||
if (iv) {
|
||||
// Shortcuts
|
||||
const IV = iv.words;
|
||||
const IV_0 = IV[0];
|
||||
const IV_1 = IV[1];
|
||||
|
||||
// Generate four subvectors
|
||||
const i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff)
|
||||
| (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00);
|
||||
const i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff)
|
||||
| (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00);
|
||||
const i1 = (i0 >>> 16) | (i2 & 0xffff0000);
|
||||
const i3 = (i2 << 16) | (i0 & 0x0000ffff);
|
||||
|
||||
// Modify counter values
|
||||
C[0] ^= i0;
|
||||
C[1] ^= i1;
|
||||
C[2] ^= i2;
|
||||
C[3] ^= i3;
|
||||
C[4] ^= i0;
|
||||
C[5] ^= i1;
|
||||
C[6] ^= i2;
|
||||
C[7] ^= i3;
|
||||
|
||||
// Iterate the system four times
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
nextState.call(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
const _M = M;
|
||||
|
||||
// Shortcut
|
||||
const X = this._X;
|
||||
|
||||
// Iterate the system
|
||||
nextState.call(this);
|
||||
|
||||
// Generate four keystream words
|
||||
S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16);
|
||||
S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16);
|
||||
S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16);
|
||||
S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16);
|
||||
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
// Swap endian
|
||||
S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff)
|
||||
| (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00);
|
||||
|
||||
// Encrypt
|
||||
_M[offset + i] ^= S[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const Rabbit = StreamCipher._createHelper(RabbitAlgo);
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
/**
|
||||
* RC4 stream cipher algorithm.
|
||||
*/
|
||||
export class RC4Algo extends StreamCipher {
|
||||
}
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const RC4: CipherObj;
|
||||
/**
|
||||
* Modified RC4 stream cipher algorithm.
|
||||
*/
|
||||
export class RC4DropAlgo extends StreamCipher {
|
||||
}
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const RC4Drop: CipherObj;
|
||||
import { CipherObj } from './cipher-core.js';
|
||||
import { StreamCipher } from './cipher-core.js';
|
||||
@@ -0,0 +1,119 @@
|
||||
import {
|
||||
StreamCipher,
|
||||
} from './cipher-core.js';
|
||||
|
||||
function generateKeystreamWord() {
|
||||
// Shortcuts
|
||||
const S = this._S;
|
||||
let i = this._i;
|
||||
let j = this._j;
|
||||
|
||||
// Generate keystream word
|
||||
let keystreamWord = 0;
|
||||
for (let n = 0; n < 4; n += 1) {
|
||||
i = (i + 1) % 256;
|
||||
j = (j + S[i]) % 256;
|
||||
|
||||
// Swap
|
||||
const t = S[i];
|
||||
S[i] = S[j];
|
||||
S[j] = t;
|
||||
|
||||
keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8);
|
||||
}
|
||||
|
||||
// Update counters
|
||||
this._i = i;
|
||||
this._j = j;
|
||||
|
||||
return keystreamWord;
|
||||
}
|
||||
|
||||
/**
|
||||
* RC4 stream cipher algorithm.
|
||||
*/
|
||||
export class RC4Algo extends StreamCipher {
|
||||
_doReset() {
|
||||
// Shortcuts
|
||||
const key = this._key;
|
||||
const keyWords = key.words;
|
||||
const keySigBytes = key.sigBytes;
|
||||
|
||||
// Init sbox
|
||||
this._S = [];
|
||||
const S = this._S;
|
||||
for (let i = 0; i < 256; i += 1) {
|
||||
S[i] = i;
|
||||
}
|
||||
|
||||
// Key setup
|
||||
for (let i = 0, j = 0; i < 256; i += 1) {
|
||||
const keyByteIndex = i % keySigBytes;
|
||||
const keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff;
|
||||
|
||||
j = (j + S[i] + keyByte) % 256;
|
||||
|
||||
// Swap
|
||||
const t = S[i];
|
||||
S[i] = S[j];
|
||||
S[j] = t;
|
||||
}
|
||||
|
||||
// Counters
|
||||
this._j = 0;
|
||||
this._i = this._j;
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
const _M = M;
|
||||
|
||||
_M[offset] ^= generateKeystreamWord.call(this);
|
||||
}
|
||||
}
|
||||
RC4Algo.keySize = 256 / 32;
|
||||
RC4Algo.ivSize = 0;
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const RC4 = StreamCipher._createHelper(RC4Algo);
|
||||
|
||||
/**
|
||||
* Modified RC4 stream cipher algorithm.
|
||||
*/
|
||||
export class RC4DropAlgo extends RC4Algo {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {number} drop The number of keystream words to drop. Default 192
|
||||
*/
|
||||
Object.assign(this.cfg, { drop: 192 });
|
||||
}
|
||||
|
||||
_doReset() {
|
||||
super._doReset.call(this);
|
||||
|
||||
// Drop
|
||||
for (let i = this.cfg.drop; i > 0; i -= 1) {
|
||||
generateKeystreamWord.call(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const RC4Drop = StreamCipher._createHelper(RC4DropAlgo);
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* RIPEMD160 hash algorithm.
|
||||
*/
|
||||
export class RIPEMD160Algo extends Hasher {}
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.RIPEMD160('message');
|
||||
* var hash = CryptoJS.RIPEMD160(wordArray);
|
||||
*/
|
||||
export const RIPEMD160: HashFn;
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacRIPEMD160(message, key);
|
||||
*/
|
||||
export const HmacRIPEMD160: HMACHashFn;
|
||||
import { Hasher } from './core.js';
|
||||
import { HashFn } from './core.js';
|
||||
import { HMACHashFn } from './core.js';
|
||||
@@ -0,0 +1,242 @@
|
||||
/** @preserve
|
||||
(c) 2012 by Cédric Mesnil. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
of conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import {
|
||||
WordArray,
|
||||
Hasher,
|
||||
} from './core.js';
|
||||
|
||||
// Constants table
|
||||
const _zl = WordArray.create([
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
|
||||
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
|
||||
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
|
||||
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]);
|
||||
const _zr = WordArray.create([
|
||||
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
|
||||
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
|
||||
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
|
||||
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
|
||||
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]);
|
||||
const _sl = WordArray.create([
|
||||
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
|
||||
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
|
||||
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
|
||||
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
|
||||
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6]);
|
||||
const _sr = WordArray.create([
|
||||
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
|
||||
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
|
||||
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
|
||||
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
|
||||
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]);
|
||||
|
||||
const _hl = WordArray.create([0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]);
|
||||
const _hr = WordArray.create([0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]);
|
||||
|
||||
const f1 = (x, y, z) => (x) ^ (y) ^ (z);
|
||||
|
||||
const f2 = (x, y, z) => ((x) & (y)) | ((~x) & (z));
|
||||
|
||||
const f3 = (x, y, z) => ((x) | (~(y))) ^ (z);
|
||||
|
||||
const f4 = (x, y, z) => ((x) & (z)) | ((y) & (~(z)));
|
||||
|
||||
const f5 = (x, y, z) => (x) ^ ((y) | (~(z)));
|
||||
|
||||
const rotl = (x, n) => (x << n) | (x >>> (32 - n));
|
||||
|
||||
/**
|
||||
* RIPEMD160 hash algorithm.
|
||||
*/
|
||||
export class RIPEMD160Algo extends Hasher {
|
||||
_doReset() {
|
||||
this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]);
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
const _M = M;
|
||||
|
||||
// Swap endian
|
||||
for (let i = 0; i < 16; i += 1) {
|
||||
// Shortcuts
|
||||
const offset_i = offset + i;
|
||||
const M_offset_i = _M[offset_i];
|
||||
|
||||
// Swap
|
||||
_M[offset_i] = (
|
||||
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff)
|
||||
| (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
|
||||
);
|
||||
}
|
||||
// Shortcut
|
||||
const H = this._hash.words;
|
||||
const hl = _hl.words;
|
||||
const hr = _hr.words;
|
||||
const zl = _zl.words;
|
||||
const zr = _zr.words;
|
||||
const sl = _sl.words;
|
||||
const sr = _sr.words;
|
||||
|
||||
// Working variables
|
||||
let al = H[0];
|
||||
let bl = H[1];
|
||||
let cl = H[2];
|
||||
let dl = H[3];
|
||||
let el = H[4];
|
||||
let ar = H[0];
|
||||
let br = H[1];
|
||||
let cr = H[2];
|
||||
let dr = H[3];
|
||||
let er = H[4];
|
||||
|
||||
// Computation
|
||||
let t;
|
||||
for (let i = 0; i < 80; i += 1) {
|
||||
t = (al + _M[offset + zl[i]]) | 0;
|
||||
if (i < 16) {
|
||||
t += f1(bl, cl, dl) + hl[0];
|
||||
} else if (i < 32) {
|
||||
t += f2(bl, cl, dl) + hl[1];
|
||||
} else if (i < 48) {
|
||||
t += f3(bl, cl, dl) + hl[2];
|
||||
} else if (i < 64) {
|
||||
t += f4(bl, cl, dl) + hl[3];
|
||||
} else { // if (i<80) {
|
||||
t += f5(bl, cl, dl) + hl[4];
|
||||
}
|
||||
t |= 0;
|
||||
t = rotl(t, sl[i]);
|
||||
t = (t + el) | 0;
|
||||
al = el;
|
||||
el = dl;
|
||||
dl = rotl(cl, 10);
|
||||
cl = bl;
|
||||
bl = t;
|
||||
|
||||
t = (ar + _M[offset + zr[i]]) | 0;
|
||||
if (i < 16) {
|
||||
t += f5(br, cr, dr) + hr[0];
|
||||
} else if (i < 32) {
|
||||
t += f4(br, cr, dr) + hr[1];
|
||||
} else if (i < 48) {
|
||||
t += f3(br, cr, dr) + hr[2];
|
||||
} else if (i < 64) {
|
||||
t += f2(br, cr, dr) + hr[3];
|
||||
} else { // if (i<80) {
|
||||
t += f1(br, cr, dr) + hr[4];
|
||||
}
|
||||
t |= 0;
|
||||
t = rotl(t, sr[i]);
|
||||
t = (t + er) | 0;
|
||||
ar = er;
|
||||
er = dr;
|
||||
dr = rotl(cr, 10);
|
||||
cr = br;
|
||||
br = t;
|
||||
}
|
||||
// Intermediate hash value
|
||||
t = (H[1] + cl + dr) | 0;
|
||||
H[1] = (H[2] + dl + er) | 0;
|
||||
H[2] = (H[3] + el + ar) | 0;
|
||||
H[3] = (H[4] + al + br) | 0;
|
||||
H[4] = (H[0] + bl + cr) | 0;
|
||||
H[0] = t;
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
// Shortcuts
|
||||
const data = this._data;
|
||||
const dataWords = data.words;
|
||||
|
||||
const nBitsTotal = this._nDataBytes * 8;
|
||||
const nBitsLeft = data.sigBytes * 8;
|
||||
|
||||
// Add padding
|
||||
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32));
|
||||
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
|
||||
(((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff)
|
||||
| (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00)
|
||||
);
|
||||
data.sigBytes = (dataWords.length + 1) * 4;
|
||||
|
||||
// Hash final blocks
|
||||
this._process();
|
||||
|
||||
// Shortcuts
|
||||
const hash = this._hash;
|
||||
const H = hash.words;
|
||||
|
||||
// Swap endian
|
||||
for (let i = 0; i < 5; i += 1) {
|
||||
// Shortcut
|
||||
const H_i = H[i];
|
||||
|
||||
// Swap
|
||||
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff)
|
||||
| (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
|
||||
}
|
||||
|
||||
// Return final computed hash
|
||||
return hash;
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
clone._hash = this._hash.clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.RIPEMD160('message');
|
||||
* var hash = CryptoJS.RIPEMD160(wordArray);
|
||||
*/
|
||||
export const RIPEMD160 = Hasher._createHelper(RIPEMD160Algo);
|
||||
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacRIPEMD160(message, key);
|
||||
*/
|
||||
export const HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160Algo);
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* SHA1 hash algorithm.
|
||||
*/
|
||||
export class SHA1Algo extends Hasher {}
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA1('message');
|
||||
* var hash = CryptoJS.SHA1(wordArray);
|
||||
*/
|
||||
export const SHA1: HashFn;
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA1(message, key);
|
||||
*/
|
||||
export const HmacSHA1: HMACHashFn;
|
||||
import { Hasher } from './core.js';
|
||||
import { HashFn } from './core.js';
|
||||
import { HMACHashFn } from './core.js';
|
||||
@@ -0,0 +1,128 @@
|
||||
import {
|
||||
WordArray,
|
||||
Hasher,
|
||||
} from './core.js';
|
||||
|
||||
// Reusable object
|
||||
const W = [];
|
||||
|
||||
/**
|
||||
* SHA-1 hash algorithm.
|
||||
*/
|
||||
export class SHA1Algo extends Hasher {
|
||||
_doReset() {
|
||||
this._hash = new WordArray([
|
||||
0x67452301,
|
||||
0xefcdab89,
|
||||
0x98badcfe,
|
||||
0x10325476,
|
||||
0xc3d2e1f0,
|
||||
]);
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
// Shortcut
|
||||
const H = this._hash.words;
|
||||
|
||||
// Working variables
|
||||
let a = H[0];
|
||||
let b = H[1];
|
||||
let c = H[2];
|
||||
let d = H[3];
|
||||
let e = H[4];
|
||||
|
||||
// Computation
|
||||
for (let i = 0; i < 80; i += 1) {
|
||||
if (i < 16) {
|
||||
W[i] = M[offset + i] | 0;
|
||||
} else {
|
||||
const n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
|
||||
W[i] = (n << 1) | (n >>> 31);
|
||||
}
|
||||
|
||||
let t = ((a << 5) | (a >>> 27)) + e + W[i];
|
||||
if (i < 20) {
|
||||
t += ((b & c) | (~b & d)) + 0x5a827999;
|
||||
} else if (i < 40) {
|
||||
t += (b ^ c ^ d) + 0x6ed9eba1;
|
||||
} else if (i < 60) {
|
||||
t += ((b & c) | (b & d) | (c & d)) - 0x70e44324;
|
||||
} else /* if (i < 80) */ {
|
||||
t += (b ^ c ^ d) - 0x359d3e2a;
|
||||
}
|
||||
|
||||
e = d;
|
||||
d = c;
|
||||
c = (b << 30) | (b >>> 2);
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
|
||||
// Intermediate hash value
|
||||
H[0] = (H[0] + a) | 0;
|
||||
H[1] = (H[1] + b) | 0;
|
||||
H[2] = (H[2] + c) | 0;
|
||||
H[3] = (H[3] + d) | 0;
|
||||
H[4] = (H[4] + e) | 0;
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
// Shortcuts
|
||||
const data = this._data;
|
||||
const dataWords = data.words;
|
||||
|
||||
const nBitsTotal = this._nDataBytes * 8;
|
||||
const nBitsLeft = data.sigBytes * 8;
|
||||
|
||||
// Add padding
|
||||
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32));
|
||||
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
|
||||
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
|
||||
data.sigBytes = dataWords.length * 4;
|
||||
|
||||
// Hash final blocks
|
||||
this._process();
|
||||
|
||||
// Return final computed hash
|
||||
return this._hash;
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
clone._hash = this._hash.clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA1('message');
|
||||
* var hash = CryptoJS.SHA1(wordArray);
|
||||
*/
|
||||
export const SHA1 = Hasher._createHelper(SHA1Algo);
|
||||
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA1(message, key);
|
||||
*/
|
||||
export const HmacSHA1 = Hasher._createHmacHelper(SHA1Algo);
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* SHA224 hash algorithm.
|
||||
*/
|
||||
export class SHA224Algo extends Hasher {}
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA224('message');
|
||||
* var hash = CryptoJS.SHA224(wordArray);
|
||||
*/
|
||||
export const SHA224: HashFn;
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA224(message, key);
|
||||
*/
|
||||
export const HmacSHA224: HMACHashFn;
|
||||
import { Hasher } from './core.js';
|
||||
import { HashFn } from './core.js';
|
||||
import { HMACHashFn } from './core.js';
|
||||
@@ -0,0 +1,60 @@
|
||||
import { WordArray } from './core.js';
|
||||
import { SHA256Algo } from './sha256.js';
|
||||
|
||||
/**
|
||||
* SHA-224 hash algorithm.
|
||||
*/
|
||||
export class SHA224Algo extends SHA256Algo {
|
||||
_doReset() {
|
||||
this._hash = new WordArray([
|
||||
0xc1059ed8,
|
||||
0x367cd507,
|
||||
0x3070dd17,
|
||||
0xf70e5939,
|
||||
0xffc00b31,
|
||||
0x68581511,
|
||||
0x64f98fa7,
|
||||
0xbefa4fa4,
|
||||
]);
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
const hash = super._doFinalize.call(this);
|
||||
|
||||
hash.sigBytes -= 4;
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA224('message');
|
||||
* var hash = CryptoJS.SHA224(wordArray);
|
||||
*/
|
||||
export const SHA224 = SHA256Algo._createHelper(SHA224Algo);
|
||||
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA224(message, key);
|
||||
*/
|
||||
export const HmacSHA224 = SHA256Algo._createHmacHelper(SHA224Algo);
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* SHA256 hash algorithm.
|
||||
*/
|
||||
export class SHA256Algo extends Hasher {}
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA256('message');
|
||||
* var hash = CryptoJS.SHA256(wordArray);
|
||||
*/
|
||||
export const SHA256: HashFn;
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA256(message, key);
|
||||
*/
|
||||
export const HmacSHA256: HMACHashFn;
|
||||
import { Hasher } from './core.js';
|
||||
import { HashFn } from './core.js';
|
||||
import { HMACHashFn } from './core.js';
|
||||
@@ -0,0 +1,171 @@
|
||||
import {
|
||||
WordArray,
|
||||
Hasher,
|
||||
} from './core.js';
|
||||
|
||||
// Initialization and round constants tables
|
||||
const H = [];
|
||||
const K = [];
|
||||
|
||||
// Compute constants
|
||||
const isPrime = (n) => {
|
||||
const sqrtN = Math.sqrt(n);
|
||||
for (let factor = 2; factor <= sqrtN; factor += 1) {
|
||||
if (!(n % factor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const getFractionalBits = n => ((n - (n | 0)) * 0x100000000) | 0;
|
||||
|
||||
let n = 2;
|
||||
let nPrime = 0;
|
||||
while (nPrime < 64) {
|
||||
if (isPrime(n)) {
|
||||
if (nPrime < 8) {
|
||||
H[nPrime] = getFractionalBits(n ** (1 / 2));
|
||||
}
|
||||
K[nPrime] = getFractionalBits(n ** (1 / 3));
|
||||
|
||||
nPrime += 1;
|
||||
}
|
||||
|
||||
n += 1;
|
||||
}
|
||||
|
||||
// Reusable object
|
||||
const W = [];
|
||||
|
||||
/**
|
||||
* SHA-256 hash algorithm.
|
||||
*/
|
||||
export class SHA256Algo extends Hasher {
|
||||
_doReset() {
|
||||
this._hash = new WordArray(H.slice(0));
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
// Shortcut
|
||||
const _H = this._hash.words;
|
||||
|
||||
// Working variables
|
||||
let a = _H[0];
|
||||
let b = _H[1];
|
||||
let c = _H[2];
|
||||
let d = _H[3];
|
||||
let e = _H[4];
|
||||
let f = _H[5];
|
||||
let g = _H[6];
|
||||
let h = _H[7];
|
||||
|
||||
// Computation
|
||||
for (let i = 0; i < 64; i += 1) {
|
||||
if (i < 16) {
|
||||
W[i] = M[offset + i] | 0;
|
||||
} else {
|
||||
const gamma0x = W[i - 15];
|
||||
const gamma0 = ((gamma0x << 25) | (gamma0x >>> 7))
|
||||
^ ((gamma0x << 14) | (gamma0x >>> 18))
|
||||
^ (gamma0x >>> 3);
|
||||
|
||||
const gamma1x = W[i - 2];
|
||||
const gamma1 = ((gamma1x << 15) | (gamma1x >>> 17))
|
||||
^ ((gamma1x << 13) | (gamma1x >>> 19))
|
||||
^ (gamma1x >>> 10);
|
||||
|
||||
W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
|
||||
}
|
||||
|
||||
const ch = (e & f) ^ (~e & g);
|
||||
const maj = (a & b) ^ (a & c) ^ (b & c);
|
||||
|
||||
const sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
|
||||
const sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25));
|
||||
|
||||
const t1 = h + sigma1 + ch + K[i] + W[i];
|
||||
const t2 = sigma0 + maj;
|
||||
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = (d + t1) | 0;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = (t1 + t2) | 0;
|
||||
}
|
||||
|
||||
// Intermediate hash value
|
||||
_H[0] = (_H[0] + a) | 0;
|
||||
_H[1] = (_H[1] + b) | 0;
|
||||
_H[2] = (_H[2] + c) | 0;
|
||||
_H[3] = (_H[3] + d) | 0;
|
||||
_H[4] = (_H[4] + e) | 0;
|
||||
_H[5] = (_H[5] + f) | 0;
|
||||
_H[6] = (_H[6] + g) | 0;
|
||||
_H[7] = (_H[7] + h) | 0;
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
// Shortcuts
|
||||
const data = this._data;
|
||||
const dataWords = data.words;
|
||||
|
||||
const nBitsTotal = this._nDataBytes * 8;
|
||||
const nBitsLeft = data.sigBytes * 8;
|
||||
|
||||
// Add padding
|
||||
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32));
|
||||
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
|
||||
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
|
||||
data.sigBytes = dataWords.length * 4;
|
||||
|
||||
// Hash final blocks
|
||||
this._process();
|
||||
|
||||
// Return final computed hash
|
||||
return this._hash;
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
clone._hash = this._hash.clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA256('message');
|
||||
* var hash = CryptoJS.SHA256(wordArray);
|
||||
*/
|
||||
export const SHA256 = Hasher._createHelper(SHA256Algo);
|
||||
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA256(message, key);
|
||||
*/
|
||||
export const HmacSHA256 = Hasher._createHmacHelper(SHA256Algo);
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* SHA3 hash algorithm.
|
||||
*/
|
||||
export class SHA3Algo extends Hasher {}
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA3('message');
|
||||
* var hash = CryptoJS.SHA3(wordArray);
|
||||
*/
|
||||
export const SHA3: HashFn;
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA3(message, key);
|
||||
*/
|
||||
export const HmacSHA3: HMACHashFn;
|
||||
import { Hasher } from './core.js';
|
||||
import { HashFn } from './core.js';
|
||||
import { HMACHashFn } from './core.js';
|
||||
@@ -0,0 +1,295 @@
|
||||
import {
|
||||
WordArray,
|
||||
Hasher,
|
||||
} from './core.js';
|
||||
import { X64Word } from './x64-core.js';
|
||||
|
||||
// Constants tables
|
||||
const RHO_OFFSETS = [];
|
||||
const PI_INDEXES = [];
|
||||
const ROUND_CONSTANTS = [];
|
||||
|
||||
// Compute Constants
|
||||
// Compute rho offset constants
|
||||
let _x = 1;
|
||||
let _y = 0;
|
||||
for (let t = 0; t < 24; t += 1) {
|
||||
RHO_OFFSETS[_x + 5 * _y] = ((t + 1) * (t + 2) / 2) % 64;
|
||||
|
||||
const newX = _y % 5;
|
||||
const newY = (2 * _x + 3 * _y) % 5;
|
||||
_x = newX;
|
||||
_y = newY;
|
||||
}
|
||||
|
||||
// Compute pi index constants
|
||||
for (let x = 0; x < 5; x += 1) {
|
||||
for (let y = 0; y < 5; y += 1) {
|
||||
PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute round constants
|
||||
let LFSR = 0x01;
|
||||
for (let i = 0; i < 24; i += 1) {
|
||||
let roundConstantMsw = 0;
|
||||
let roundConstantLsw = 0;
|
||||
|
||||
for (let j = 0; j < 7; j += 1) {
|
||||
if (LFSR & 0x01) {
|
||||
const bitPosition = (1 << j) - 1;
|
||||
if (bitPosition < 32) {
|
||||
roundConstantLsw ^= 1 << bitPosition;
|
||||
} else /* if (bitPosition >= 32) */ {
|
||||
roundConstantMsw ^= 1 << (bitPosition - 32);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute next LFSR
|
||||
if (LFSR & 0x80) {
|
||||
// Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1
|
||||
LFSR = (LFSR << 1) ^ 0x71;
|
||||
} else {
|
||||
LFSR <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw);
|
||||
}
|
||||
|
||||
// Reusable objects for temporary values
|
||||
const T = [];
|
||||
for (let i = 0; i < 25; i += 1) {
|
||||
T[i] = X64Word.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA-3 hash algorithm.
|
||||
*/
|
||||
export class SHA3Algo extends Hasher {
|
||||
constructor(cfg) {
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {number} outputLength
|
||||
* The desired number of bits in the output hash.
|
||||
* Only values permitted are: 224, 256, 384, 512.
|
||||
* Default: 512
|
||||
*/
|
||||
super(Object.assign(
|
||||
{ outputLength: 512 },
|
||||
cfg,
|
||||
));
|
||||
}
|
||||
|
||||
_doReset() {
|
||||
this._state = [];
|
||||
const state = this._state;
|
||||
for (let i = 0; i < 25; i += 1) {
|
||||
state[i] = new X64Word();
|
||||
}
|
||||
|
||||
this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32;
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
// Shortcuts
|
||||
const state = this._state;
|
||||
const nBlockSizeLanes = this.blockSize / 2;
|
||||
|
||||
// Absorb
|
||||
for (let i = 0; i < nBlockSizeLanes; i += 1) {
|
||||
// Shortcuts
|
||||
let M2i = M[offset + 2 * i];
|
||||
let M2i1 = M[offset + 2 * i + 1];
|
||||
|
||||
// Swap endian
|
||||
M2i = (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff)
|
||||
| (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00);
|
||||
M2i1 = (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff)
|
||||
| (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00);
|
||||
|
||||
// Absorb message into state
|
||||
const lane = state[i];
|
||||
lane.high ^= M2i1;
|
||||
lane.low ^= M2i;
|
||||
}
|
||||
|
||||
// Rounds
|
||||
for (let round = 0; round < 24; round += 1) {
|
||||
// Theta
|
||||
for (let x = 0; x < 5; x += 1) {
|
||||
// Mix column lanes
|
||||
let tMsw = 0;
|
||||
let tLsw = 0;
|
||||
for (let y = 0; y < 5; y += 1) {
|
||||
const lane = state[x + 5 * y];
|
||||
tMsw ^= lane.high;
|
||||
tLsw ^= lane.low;
|
||||
}
|
||||
|
||||
// Temporary values
|
||||
const Tx = T[x];
|
||||
Tx.high = tMsw;
|
||||
Tx.low = tLsw;
|
||||
}
|
||||
for (let x = 0; x < 5; x += 1) {
|
||||
// Shortcuts
|
||||
const Tx4 = T[(x + 4) % 5];
|
||||
const Tx1 = T[(x + 1) % 5];
|
||||
const Tx1Msw = Tx1.high;
|
||||
const Tx1Lsw = Tx1.low;
|
||||
|
||||
// Mix surrounding columns
|
||||
const tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31));
|
||||
const tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31));
|
||||
for (let y = 0; y < 5; y += 1) {
|
||||
const lane = state[x + 5 * y];
|
||||
lane.high ^= tMsw;
|
||||
lane.low ^= tLsw;
|
||||
}
|
||||
}
|
||||
|
||||
// Rho Pi
|
||||
for (let laneIndex = 1; laneIndex < 25; laneIndex += 1) {
|
||||
let tMsw;
|
||||
let tLsw;
|
||||
|
||||
// Shortcuts
|
||||
const lane = state[laneIndex];
|
||||
const laneMsw = lane.high;
|
||||
const laneLsw = lane.low;
|
||||
const rhoOffset = RHO_OFFSETS[laneIndex];
|
||||
|
||||
// Rotate lanes
|
||||
if (rhoOffset < 32) {
|
||||
tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset));
|
||||
tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset));
|
||||
} else /* if (rhoOffset >= 32) */ {
|
||||
tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset));
|
||||
tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset));
|
||||
}
|
||||
|
||||
// Transpose lanes
|
||||
const TPiLane = T[PI_INDEXES[laneIndex]];
|
||||
TPiLane.high = tMsw;
|
||||
TPiLane.low = tLsw;
|
||||
}
|
||||
|
||||
// Rho pi at x = y = 0
|
||||
const T0 = T[0];
|
||||
const state0 = state[0];
|
||||
T0.high = state0.high;
|
||||
T0.low = state0.low;
|
||||
|
||||
// Chi
|
||||
for (let x = 0; x < 5; x += 1) {
|
||||
for (let y = 0; y < 5; y += 1) {
|
||||
// Shortcuts
|
||||
const laneIndex = x + 5 * y;
|
||||
const lane = state[laneIndex];
|
||||
const TLane = T[laneIndex];
|
||||
const Tx1Lane = T[((x + 1) % 5) + 5 * y];
|
||||
const Tx2Lane = T[((x + 2) % 5) + 5 * y];
|
||||
|
||||
// Mix rows
|
||||
lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high);
|
||||
lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low);
|
||||
}
|
||||
}
|
||||
|
||||
// Iota
|
||||
const lane = state[0];
|
||||
const roundConstant = ROUND_CONSTANTS[round];
|
||||
lane.high ^= roundConstant.high;
|
||||
lane.low ^= roundConstant.low;
|
||||
}
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
// Shortcuts
|
||||
const data = this._data;
|
||||
const dataWords = data.words;
|
||||
const nBitsLeft = data.sigBytes * 8;
|
||||
const blockSizeBits = this.blockSize * 32;
|
||||
|
||||
// Add padding
|
||||
dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - (nBitsLeft % 32));
|
||||
dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80;
|
||||
data.sigBytes = dataWords.length * 4;
|
||||
|
||||
// Hash final blocks
|
||||
this._process();
|
||||
|
||||
// Shortcuts
|
||||
const state = this._state;
|
||||
const outputLengthBytes = this.cfg.outputLength / 8;
|
||||
const outputLengthLanes = outputLengthBytes / 8;
|
||||
|
||||
// Squeeze
|
||||
const hashWords = [];
|
||||
for (let i = 0; i < outputLengthLanes; i += 1) {
|
||||
// Shortcuts
|
||||
const lane = state[i];
|
||||
let laneMsw = lane.high;
|
||||
let laneLsw = lane.low;
|
||||
|
||||
// Swap endian
|
||||
laneMsw = (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff)
|
||||
| (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00);
|
||||
laneLsw = (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff)
|
||||
| (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00);
|
||||
|
||||
// Squeeze state to retrieve hash
|
||||
hashWords.push(laneLsw);
|
||||
hashWords.push(laneMsw);
|
||||
}
|
||||
|
||||
// Return final computed hash
|
||||
return new WordArray(hashWords, outputLengthBytes);
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
|
||||
clone._state = this._state.slice(0);
|
||||
const state = clone._state;
|
||||
for (let i = 0; i < 25; i += 1) {
|
||||
state[i] = state[i].clone();
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA3('message');
|
||||
* var hash = CryptoJS.SHA3(wordArray);
|
||||
*/
|
||||
export const SHA3 = Hasher._createHelper(SHA3Algo);
|
||||
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA3(message, key);
|
||||
*/
|
||||
export const HmacSHA3 = Hasher._createHmacHelper(SHA3Algo);
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* SHA384 hash algorithm.
|
||||
*/
|
||||
export class SHA384Algo extends Hasher {}
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA384('message');
|
||||
* var hash = CryptoJS.SHA384(wordArray);
|
||||
*/
|
||||
export const SHA384: HashFn;
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA384(message, key);
|
||||
*/
|
||||
export const HmacSHA384: HMACHashFn;
|
||||
import { Hasher } from './core.js';
|
||||
import { HashFn } from './core.js';
|
||||
import { HMACHashFn } from './core.js';
|
||||
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
X64Word,
|
||||
X64WordArray,
|
||||
} from './x64-core.js';
|
||||
import { SHA512Algo } from './sha512.js';
|
||||
|
||||
/**
|
||||
* SHA-384 hash algorithm.
|
||||
*/
|
||||
export class SHA384Algo extends SHA512Algo {
|
||||
_doReset() {
|
||||
this._hash = new X64WordArray([
|
||||
new X64Word(0xcbbb9d5d, 0xc1059ed8),
|
||||
new X64Word(0x629a292a, 0x367cd507),
|
||||
new X64Word(0x9159015a, 0x3070dd17),
|
||||
new X64Word(0x152fecd8, 0xf70e5939),
|
||||
new X64Word(0x67332667, 0xffc00b31),
|
||||
new X64Word(0x8eb44a87, 0x68581511),
|
||||
new X64Word(0xdb0c2e0d, 0x64f98fa7),
|
||||
new X64Word(0x47b5481d, 0xbefa4fa4),
|
||||
]);
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
const hash = super._doFinalize.call(this);
|
||||
|
||||
hash.sigBytes -= 16;
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA384('message');
|
||||
* var hash = CryptoJS.SHA384(wordArray);
|
||||
*/
|
||||
export const SHA384 = SHA512Algo._createHelper(SHA384Algo);
|
||||
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA384(message, key);
|
||||
*/
|
||||
export const HmacSHA384 = SHA512Algo._createHmacHelper(SHA384Algo);
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* SHA512 hash algorithm.
|
||||
*/
|
||||
export class SHA512Algo extends Hasher {}
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA512('message');
|
||||
* var hash = CryptoJS.SHA512(wordArray);
|
||||
*/
|
||||
export const SHA512: HashFn;
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA512(message, key);
|
||||
*/
|
||||
export const HmacSHA512: HMACHashFn;
|
||||
import { Hasher } from './core.js';
|
||||
import { HashFn } from './core.js';
|
||||
import { HMACHashFn } from './core.js';
|
||||
@@ -0,0 +1,369 @@
|
||||
import { Hasher } from './core.js';
|
||||
import {
|
||||
X64Word,
|
||||
X64WordArray,
|
||||
} from './x64-core.js';
|
||||
|
||||
// Constants
|
||||
const K = [
|
||||
new X64Word(0x428a2f98, 0xd728ae22),
|
||||
new X64Word(0x71374491, 0x23ef65cd),
|
||||
new X64Word(0xb5c0fbcf, 0xec4d3b2f),
|
||||
new X64Word(0xe9b5dba5, 0x8189dbbc),
|
||||
new X64Word(0x3956c25b, 0xf348b538),
|
||||
new X64Word(0x59f111f1, 0xb605d019),
|
||||
new X64Word(0x923f82a4, 0xaf194f9b),
|
||||
new X64Word(0xab1c5ed5, 0xda6d8118),
|
||||
new X64Word(0xd807aa98, 0xa3030242),
|
||||
new X64Word(0x12835b01, 0x45706fbe),
|
||||
new X64Word(0x243185be, 0x4ee4b28c),
|
||||
new X64Word(0x550c7dc3, 0xd5ffb4e2),
|
||||
new X64Word(0x72be5d74, 0xf27b896f),
|
||||
new X64Word(0x80deb1fe, 0x3b1696b1),
|
||||
new X64Word(0x9bdc06a7, 0x25c71235),
|
||||
new X64Word(0xc19bf174, 0xcf692694),
|
||||
new X64Word(0xe49b69c1, 0x9ef14ad2),
|
||||
new X64Word(0xefbe4786, 0x384f25e3),
|
||||
new X64Word(0x0fc19dc6, 0x8b8cd5b5),
|
||||
new X64Word(0x240ca1cc, 0x77ac9c65),
|
||||
new X64Word(0x2de92c6f, 0x592b0275),
|
||||
new X64Word(0x4a7484aa, 0x6ea6e483),
|
||||
new X64Word(0x5cb0a9dc, 0xbd41fbd4),
|
||||
new X64Word(0x76f988da, 0x831153b5),
|
||||
new X64Word(0x983e5152, 0xee66dfab),
|
||||
new X64Word(0xa831c66d, 0x2db43210),
|
||||
new X64Word(0xb00327c8, 0x98fb213f),
|
||||
new X64Word(0xbf597fc7, 0xbeef0ee4),
|
||||
new X64Word(0xc6e00bf3, 0x3da88fc2),
|
||||
new X64Word(0xd5a79147, 0x930aa725),
|
||||
new X64Word(0x06ca6351, 0xe003826f),
|
||||
new X64Word(0x14292967, 0x0a0e6e70),
|
||||
new X64Word(0x27b70a85, 0x46d22ffc),
|
||||
new X64Word(0x2e1b2138, 0x5c26c926),
|
||||
new X64Word(0x4d2c6dfc, 0x5ac42aed),
|
||||
new X64Word(0x53380d13, 0x9d95b3df),
|
||||
new X64Word(0x650a7354, 0x8baf63de),
|
||||
new X64Word(0x766a0abb, 0x3c77b2a8),
|
||||
new X64Word(0x81c2c92e, 0x47edaee6),
|
||||
new X64Word(0x92722c85, 0x1482353b),
|
||||
new X64Word(0xa2bfe8a1, 0x4cf10364),
|
||||
new X64Word(0xa81a664b, 0xbc423001),
|
||||
new X64Word(0xc24b8b70, 0xd0f89791),
|
||||
new X64Word(0xc76c51a3, 0x0654be30),
|
||||
new X64Word(0xd192e819, 0xd6ef5218),
|
||||
new X64Word(0xd6990624, 0x5565a910),
|
||||
new X64Word(0xf40e3585, 0x5771202a),
|
||||
new X64Word(0x106aa070, 0x32bbd1b8),
|
||||
new X64Word(0x19a4c116, 0xb8d2d0c8),
|
||||
new X64Word(0x1e376c08, 0x5141ab53),
|
||||
new X64Word(0x2748774c, 0xdf8eeb99),
|
||||
new X64Word(0x34b0bcb5, 0xe19b48a8),
|
||||
new X64Word(0x391c0cb3, 0xc5c95a63),
|
||||
new X64Word(0x4ed8aa4a, 0xe3418acb),
|
||||
new X64Word(0x5b9cca4f, 0x7763e373),
|
||||
new X64Word(0x682e6ff3, 0xd6b2b8a3),
|
||||
new X64Word(0x748f82ee, 0x5defb2fc),
|
||||
new X64Word(0x78a5636f, 0x43172f60),
|
||||
new X64Word(0x84c87814, 0xa1f0ab72),
|
||||
new X64Word(0x8cc70208, 0x1a6439ec),
|
||||
new X64Word(0x90befffa, 0x23631e28),
|
||||
new X64Word(0xa4506ceb, 0xde82bde9),
|
||||
new X64Word(0xbef9a3f7, 0xb2c67915),
|
||||
new X64Word(0xc67178f2, 0xe372532b),
|
||||
new X64Word(0xca273ece, 0xea26619c),
|
||||
new X64Word(0xd186b8c7, 0x21c0c207),
|
||||
new X64Word(0xeada7dd6, 0xcde0eb1e),
|
||||
new X64Word(0xf57d4f7f, 0xee6ed178),
|
||||
new X64Word(0x06f067aa, 0x72176fba),
|
||||
new X64Word(0x0a637dc5, 0xa2c898a6),
|
||||
new X64Word(0x113f9804, 0xbef90dae),
|
||||
new X64Word(0x1b710b35, 0x131c471b),
|
||||
new X64Word(0x28db77f5, 0x23047d84),
|
||||
new X64Word(0x32caab7b, 0x40c72493),
|
||||
new X64Word(0x3c9ebe0a, 0x15c9bebc),
|
||||
new X64Word(0x431d67c4, 0x9c100d4c),
|
||||
new X64Word(0x4cc5d4be, 0xcb3e42b6),
|
||||
new X64Word(0x597f299c, 0xfc657e2a),
|
||||
new X64Word(0x5fcb6fab, 0x3ad6faec),
|
||||
new X64Word(0x6c44198c, 0x4a475817),
|
||||
];
|
||||
|
||||
// Reusable objects
|
||||
const W = [];
|
||||
for (let i = 0; i < 80; i += 1) {
|
||||
W[i] = new X64Word();
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA-512 hash algorithm.
|
||||
*/
|
||||
export class SHA512Algo extends Hasher {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.blockSize = 1024 / 32;
|
||||
}
|
||||
|
||||
_doReset() {
|
||||
this._hash = new X64WordArray([
|
||||
new X64Word(0x6a09e667, 0xf3bcc908),
|
||||
new X64Word(0xbb67ae85, 0x84caa73b),
|
||||
new X64Word(0x3c6ef372, 0xfe94f82b),
|
||||
new X64Word(0xa54ff53a, 0x5f1d36f1),
|
||||
new X64Word(0x510e527f, 0xade682d1),
|
||||
new X64Word(0x9b05688c, 0x2b3e6c1f),
|
||||
new X64Word(0x1f83d9ab, 0xfb41bd6b),
|
||||
new X64Word(0x5be0cd19, 0x137e2179),
|
||||
]);
|
||||
}
|
||||
|
||||
_doProcessBlock(M, offset) {
|
||||
// Shortcuts
|
||||
const H = this._hash.words;
|
||||
|
||||
const H0 = H[0];
|
||||
const H1 = H[1];
|
||||
const H2 = H[2];
|
||||
const H3 = H[3];
|
||||
const H4 = H[4];
|
||||
const H5 = H[5];
|
||||
const H6 = H[6];
|
||||
const H7 = H[7];
|
||||
|
||||
const H0h = H0.high;
|
||||
let H0l = H0.low;
|
||||
const H1h = H1.high;
|
||||
let H1l = H1.low;
|
||||
const H2h = H2.high;
|
||||
let H2l = H2.low;
|
||||
const H3h = H3.high;
|
||||
let H3l = H3.low;
|
||||
const H4h = H4.high;
|
||||
let H4l = H4.low;
|
||||
const H5h = H5.high;
|
||||
let H5l = H5.low;
|
||||
const H6h = H6.high;
|
||||
let H6l = H6.low;
|
||||
const H7h = H7.high;
|
||||
let H7l = H7.low;
|
||||
|
||||
// Working variables
|
||||
let ah = H0h;
|
||||
let al = H0l;
|
||||
let bh = H1h;
|
||||
let bl = H1l;
|
||||
let ch = H2h;
|
||||
let cl = H2l;
|
||||
let dh = H3h;
|
||||
let dl = H3l;
|
||||
let eh = H4h;
|
||||
let el = H4l;
|
||||
let fh = H5h;
|
||||
let fl = H5l;
|
||||
let gh = H6h;
|
||||
let gl = H6l;
|
||||
let hh = H7h;
|
||||
let hl = H7l;
|
||||
|
||||
// Rounds
|
||||
for (let i = 0; i < 80; i += 1) {
|
||||
let Wil;
|
||||
let Wih;
|
||||
|
||||
// Shortcut
|
||||
const Wi = W[i];
|
||||
|
||||
// Extend message
|
||||
if (i < 16) {
|
||||
Wi.high = M[offset + i * 2] | 0;
|
||||
Wih = Wi.high;
|
||||
Wi.low = M[offset + i * 2 + 1] | 0;
|
||||
Wil = Wi.low;
|
||||
} else {
|
||||
// Gamma0
|
||||
const gamma0x = W[i - 15];
|
||||
const gamma0xh = gamma0x.high;
|
||||
const gamma0xl = gamma0x.low;
|
||||
const gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31))
|
||||
^ ((gamma0xh >>> 8) | (gamma0xl << 24))
|
||||
^ (gamma0xh >>> 7);
|
||||
const gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31))
|
||||
^ ((gamma0xl >>> 8) | (gamma0xh << 24))
|
||||
^ ((gamma0xl >>> 7) | (gamma0xh << 25));
|
||||
|
||||
// Gamma1
|
||||
const gamma1x = W[i - 2];
|
||||
const gamma1xh = gamma1x.high;
|
||||
const gamma1xl = gamma1x.low;
|
||||
const gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13))
|
||||
^ ((gamma1xh << 3) | (gamma1xl >>> 29))
|
||||
^ (gamma1xh >>> 6);
|
||||
const gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13))
|
||||
^ ((gamma1xl << 3) | (gamma1xh >>> 29))
|
||||
^ ((gamma1xl >>> 6) | (gamma1xh << 26));
|
||||
|
||||
// W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
|
||||
const Wi7 = W[i - 7];
|
||||
const Wi7h = Wi7.high;
|
||||
const Wi7l = Wi7.low;
|
||||
|
||||
const Wi16 = W[i - 16];
|
||||
const Wi16h = Wi16.high;
|
||||
const Wi16l = Wi16.low;
|
||||
|
||||
Wil = gamma0l + Wi7l;
|
||||
Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0);
|
||||
Wil += gamma1l;
|
||||
Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0);
|
||||
Wil += Wi16l;
|
||||
Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0);
|
||||
|
||||
Wi.high = Wih;
|
||||
Wi.low = Wil;
|
||||
}
|
||||
|
||||
const chh = (eh & fh) ^ (~eh & gh);
|
||||
const chl = (el & fl) ^ (~el & gl);
|
||||
const majh = (ah & bh) ^ (ah & ch) ^ (bh & ch);
|
||||
const majl = (al & bl) ^ (al & cl) ^ (bl & cl);
|
||||
|
||||
const sigma0h = ((ah >>> 28) | (al << 4))
|
||||
^ ((ah << 30) | (al >>> 2))
|
||||
^ ((ah << 25) | (al >>> 7));
|
||||
const sigma0l = ((al >>> 28) | (ah << 4))
|
||||
^ ((al << 30) | (ah >>> 2))
|
||||
^ ((al << 25) | (ah >>> 7));
|
||||
const sigma1h = ((eh >>> 14) | (el << 18))
|
||||
^ ((eh >>> 18) | (el << 14))
|
||||
^ ((eh << 23) | (el >>> 9));
|
||||
const sigma1l = ((el >>> 14) | (eh << 18))
|
||||
^ ((el >>> 18) | (eh << 14))
|
||||
^ ((el << 23) | (eh >>> 9));
|
||||
|
||||
// t1 = h + sigma1 + ch + K[i] + W[i]
|
||||
const Ki = K[i];
|
||||
const Kih = Ki.high;
|
||||
const Kil = Ki.low;
|
||||
|
||||
let t1l = hl + sigma1l;
|
||||
let t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0);
|
||||
t1l += chl;
|
||||
t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0);
|
||||
t1l += Kil;
|
||||
t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0);
|
||||
t1l += Wil;
|
||||
t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0);
|
||||
|
||||
// t2 = sigma0 + maj
|
||||
const t2l = sigma0l + majl;
|
||||
const t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0);
|
||||
|
||||
// Update working variables
|
||||
hh = gh;
|
||||
hl = gl;
|
||||
gh = fh;
|
||||
gl = fl;
|
||||
fh = eh;
|
||||
fl = el;
|
||||
el = (dl + t1l) | 0;
|
||||
eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0;
|
||||
dh = ch;
|
||||
dl = cl;
|
||||
ch = bh;
|
||||
cl = bl;
|
||||
bh = ah;
|
||||
bl = al;
|
||||
al = (t1l + t2l) | 0;
|
||||
ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0;
|
||||
}
|
||||
|
||||
// Intermediate hash value
|
||||
H0.low = (H0l + al);
|
||||
H0l = H0.low;
|
||||
H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0));
|
||||
H1.low = (H1l + bl);
|
||||
H1l = H1.low;
|
||||
H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0));
|
||||
H2.low = (H2l + cl);
|
||||
H2l = H2.low;
|
||||
H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0));
|
||||
H3.low = (H3l + dl);
|
||||
H3l = H3.low;
|
||||
H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0));
|
||||
H4.low = (H4l + el);
|
||||
H4l = H4.low;
|
||||
H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0));
|
||||
H5.low = (H5l + fl);
|
||||
H5l = H5.low;
|
||||
H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0));
|
||||
H6.low = (H6l + gl);
|
||||
H6l = H6.low;
|
||||
H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0));
|
||||
H7.low = (H7l + hl);
|
||||
H7l = H7.low;
|
||||
H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0));
|
||||
}
|
||||
|
||||
_doFinalize() {
|
||||
// Shortcuts
|
||||
const data = this._data;
|
||||
const dataWords = data.words;
|
||||
|
||||
const nBitsTotal = this._nDataBytes * 8;
|
||||
const nBitsLeft = data.sigBytes * 8;
|
||||
|
||||
// Add padding
|
||||
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32));
|
||||
dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000);
|
||||
dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal;
|
||||
data.sigBytes = dataWords.length * 4;
|
||||
|
||||
// Hash final blocks
|
||||
this._process();
|
||||
|
||||
// Convert hash to 32-bit word array before returning
|
||||
const hash = this._hash.toX32();
|
||||
|
||||
// Return final computed hash
|
||||
return hash;
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
clone._hash = this._hash.clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut function to the hasher's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = CryptoJS.SHA512('message');
|
||||
* var hash = CryptoJS.SHA512(wordArray);
|
||||
*/
|
||||
export const SHA512 = Hasher._createHelper(SHA512Algo);
|
||||
|
||||
/**
|
||||
* Shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {WordArray|string} message The message to hash.
|
||||
* @param {WordArray|string} key The secret key.
|
||||
*
|
||||
* @return {WordArray} The HMAC.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hmac = CryptoJS.HmacSHA512(message, key);
|
||||
*/
|
||||
export const HmacSHA512 = Hasher._createHmacHelper(SHA512Algo);
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* DES block cipher algorithm.
|
||||
*/
|
||||
export class DESAlgo extends BlockCipher {
|
||||
}
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.DES.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const DES: CipherObj;
|
||||
/**
|
||||
* Triple-DES block cipher algorithm.
|
||||
*/
|
||||
export class TripleDESAlgo extends BlockCipher {
|
||||
}
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const TripleDES: CipherObj;
|
||||
import { CipherObj } from './cipher-core.js';
|
||||
import { BlockCipher } from './cipher-core.js';
|
||||
@@ -0,0 +1,766 @@
|
||||
import {
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
import {
|
||||
BlockCipher,
|
||||
} from './cipher-core.js';
|
||||
|
||||
// Permuted Choice 1 constants
|
||||
const PC1 = [
|
||||
57, 49, 41, 33, 25, 17, 9, 1,
|
||||
58, 50, 42, 34, 26, 18, 10, 2,
|
||||
59, 51, 43, 35, 27, 19, 11, 3,
|
||||
60, 52, 44, 36, 63, 55, 47, 39,
|
||||
31, 23, 15, 7, 62, 54, 46, 38,
|
||||
30, 22, 14, 6, 61, 53, 45, 37,
|
||||
29, 21, 13, 5, 28, 20, 12, 4,
|
||||
];
|
||||
|
||||
// Permuted Choice 2 constants
|
||||
const PC2 = [
|
||||
14, 17, 11, 24, 1, 5,
|
||||
3, 28, 15, 6, 21, 10,
|
||||
23, 19, 12, 4, 26, 8,
|
||||
16, 7, 27, 20, 13, 2,
|
||||
41, 52, 31, 37, 47, 55,
|
||||
30, 40, 51, 45, 33, 48,
|
||||
44, 49, 39, 56, 34, 53,
|
||||
46, 42, 50, 36, 29, 32,
|
||||
];
|
||||
|
||||
// Cumulative bit shift constants
|
||||
const BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28];
|
||||
|
||||
// SBOXes and round permutation constants
|
||||
const SBOX_P = [
|
||||
{
|
||||
0x0: 0x808200,
|
||||
0x10000000: 0x8000,
|
||||
0x20000000: 0x808002,
|
||||
0x30000000: 0x2,
|
||||
0x40000000: 0x200,
|
||||
0x50000000: 0x808202,
|
||||
0x60000000: 0x800202,
|
||||
0x70000000: 0x800000,
|
||||
0x80000000: 0x202,
|
||||
0x90000000: 0x800200,
|
||||
0xa0000000: 0x8200,
|
||||
0xb0000000: 0x808000,
|
||||
0xc0000000: 0x8002,
|
||||
0xd0000000: 0x800002,
|
||||
0xe0000000: 0x0,
|
||||
0xf0000000: 0x8202,
|
||||
0x8000000: 0x0,
|
||||
0x18000000: 0x808202,
|
||||
0x28000000: 0x8202,
|
||||
0x38000000: 0x8000,
|
||||
0x48000000: 0x808200,
|
||||
0x58000000: 0x200,
|
||||
0x68000000: 0x808002,
|
||||
0x78000000: 0x2,
|
||||
0x88000000: 0x800200,
|
||||
0x98000000: 0x8200,
|
||||
0xa8000000: 0x808000,
|
||||
0xb8000000: 0x800202,
|
||||
0xc8000000: 0x800002,
|
||||
0xd8000000: 0x8002,
|
||||
0xe8000000: 0x202,
|
||||
0xf8000000: 0x800000,
|
||||
0x1: 0x8000,
|
||||
0x10000001: 0x2,
|
||||
0x20000001: 0x808200,
|
||||
0x30000001: 0x800000,
|
||||
0x40000001: 0x808002,
|
||||
0x50000001: 0x8200,
|
||||
0x60000001: 0x200,
|
||||
0x70000001: 0x800202,
|
||||
0x80000001: 0x808202,
|
||||
0x90000001: 0x808000,
|
||||
0xa0000001: 0x800002,
|
||||
0xb0000001: 0x8202,
|
||||
0xc0000001: 0x202,
|
||||
0xd0000001: 0x800200,
|
||||
0xe0000001: 0x8002,
|
||||
0xf0000001: 0x0,
|
||||
0x8000001: 0x808202,
|
||||
0x18000001: 0x808000,
|
||||
0x28000001: 0x800000,
|
||||
0x38000001: 0x200,
|
||||
0x48000001: 0x8000,
|
||||
0x58000001: 0x800002,
|
||||
0x68000001: 0x2,
|
||||
0x78000001: 0x8202,
|
||||
0x88000001: 0x8002,
|
||||
0x98000001: 0x800202,
|
||||
0xa8000001: 0x202,
|
||||
0xb8000001: 0x808200,
|
||||
0xc8000001: 0x800200,
|
||||
0xd8000001: 0x0,
|
||||
0xe8000001: 0x8200,
|
||||
0xf8000001: 0x808002,
|
||||
},
|
||||
{
|
||||
0x0: 0x40084010,
|
||||
0x1000000: 0x4000,
|
||||
0x2000000: 0x80000,
|
||||
0x3000000: 0x40080010,
|
||||
0x4000000: 0x40000010,
|
||||
0x5000000: 0x40084000,
|
||||
0x6000000: 0x40004000,
|
||||
0x7000000: 0x10,
|
||||
0x8000000: 0x84000,
|
||||
0x9000000: 0x40004010,
|
||||
0xa000000: 0x40000000,
|
||||
0xb000000: 0x84010,
|
||||
0xc000000: 0x80010,
|
||||
0xd000000: 0x0,
|
||||
0xe000000: 0x4010,
|
||||
0xf000000: 0x40080000,
|
||||
0x800000: 0x40004000,
|
||||
0x1800000: 0x84010,
|
||||
0x2800000: 0x10,
|
||||
0x3800000: 0x40004010,
|
||||
0x4800000: 0x40084010,
|
||||
0x5800000: 0x40000000,
|
||||
0x6800000: 0x80000,
|
||||
0x7800000: 0x40080010,
|
||||
0x8800000: 0x80010,
|
||||
0x9800000: 0x0,
|
||||
0xa800000: 0x4000,
|
||||
0xb800000: 0x40080000,
|
||||
0xc800000: 0x40000010,
|
||||
0xd800000: 0x84000,
|
||||
0xe800000: 0x40084000,
|
||||
0xf800000: 0x4010,
|
||||
0x10000000: 0x0,
|
||||
0x11000000: 0x40080010,
|
||||
0x12000000: 0x40004010,
|
||||
0x13000000: 0x40084000,
|
||||
0x14000000: 0x40080000,
|
||||
0x15000000: 0x10,
|
||||
0x16000000: 0x84010,
|
||||
0x17000000: 0x4000,
|
||||
0x18000000: 0x4010,
|
||||
0x19000000: 0x80000,
|
||||
0x1a000000: 0x80010,
|
||||
0x1b000000: 0x40000010,
|
||||
0x1c000000: 0x84000,
|
||||
0x1d000000: 0x40004000,
|
||||
0x1e000000: 0x40000000,
|
||||
0x1f000000: 0x40084010,
|
||||
0x10800000: 0x84010,
|
||||
0x11800000: 0x80000,
|
||||
0x12800000: 0x40080000,
|
||||
0x13800000: 0x4000,
|
||||
0x14800000: 0x40004000,
|
||||
0x15800000: 0x40084010,
|
||||
0x16800000: 0x10,
|
||||
0x17800000: 0x40000000,
|
||||
0x18800000: 0x40084000,
|
||||
0x19800000: 0x40000010,
|
||||
0x1a800000: 0x40004010,
|
||||
0x1b800000: 0x80010,
|
||||
0x1c800000: 0x0,
|
||||
0x1d800000: 0x4010,
|
||||
0x1e800000: 0x40080010,
|
||||
0x1f800000: 0x84000,
|
||||
},
|
||||
{
|
||||
0x0: 0x104,
|
||||
0x100000: 0x0,
|
||||
0x200000: 0x4000100,
|
||||
0x300000: 0x10104,
|
||||
0x400000: 0x10004,
|
||||
0x500000: 0x4000004,
|
||||
0x600000: 0x4010104,
|
||||
0x700000: 0x4010000,
|
||||
0x800000: 0x4000000,
|
||||
0x900000: 0x4010100,
|
||||
0xa00000: 0x10100,
|
||||
0xb00000: 0x4010004,
|
||||
0xc00000: 0x4000104,
|
||||
0xd00000: 0x10000,
|
||||
0xe00000: 0x4,
|
||||
0xf00000: 0x100,
|
||||
0x80000: 0x4010100,
|
||||
0x180000: 0x4010004,
|
||||
0x280000: 0x0,
|
||||
0x380000: 0x4000100,
|
||||
0x480000: 0x4000004,
|
||||
0x580000: 0x10000,
|
||||
0x680000: 0x10004,
|
||||
0x780000: 0x104,
|
||||
0x880000: 0x4,
|
||||
0x980000: 0x100,
|
||||
0xa80000: 0x4010000,
|
||||
0xb80000: 0x10104,
|
||||
0xc80000: 0x10100,
|
||||
0xd80000: 0x4000104,
|
||||
0xe80000: 0x4010104,
|
||||
0xf80000: 0x4000000,
|
||||
0x1000000: 0x4010100,
|
||||
0x1100000: 0x10004,
|
||||
0x1200000: 0x10000,
|
||||
0x1300000: 0x4000100,
|
||||
0x1400000: 0x100,
|
||||
0x1500000: 0x4010104,
|
||||
0x1600000: 0x4000004,
|
||||
0x1700000: 0x0,
|
||||
0x1800000: 0x4000104,
|
||||
0x1900000: 0x4000000,
|
||||
0x1a00000: 0x4,
|
||||
0x1b00000: 0x10100,
|
||||
0x1c00000: 0x4010000,
|
||||
0x1d00000: 0x104,
|
||||
0x1e00000: 0x10104,
|
||||
0x1f00000: 0x4010004,
|
||||
0x1080000: 0x4000000,
|
||||
0x1180000: 0x104,
|
||||
0x1280000: 0x4010100,
|
||||
0x1380000: 0x0,
|
||||
0x1480000: 0x10004,
|
||||
0x1580000: 0x4000100,
|
||||
0x1680000: 0x100,
|
||||
0x1780000: 0x4010004,
|
||||
0x1880000: 0x10000,
|
||||
0x1980000: 0x4010104,
|
||||
0x1a80000: 0x10104,
|
||||
0x1b80000: 0x4000004,
|
||||
0x1c80000: 0x4000104,
|
||||
0x1d80000: 0x4010000,
|
||||
0x1e80000: 0x4,
|
||||
0x1f80000: 0x10100,
|
||||
},
|
||||
{
|
||||
0x0: 0x80401000,
|
||||
0x10000: 0x80001040,
|
||||
0x20000: 0x401040,
|
||||
0x30000: 0x80400000,
|
||||
0x40000: 0x0,
|
||||
0x50000: 0x401000,
|
||||
0x60000: 0x80000040,
|
||||
0x70000: 0x400040,
|
||||
0x80000: 0x80000000,
|
||||
0x90000: 0x400000,
|
||||
0xa0000: 0x40,
|
||||
0xb0000: 0x80001000,
|
||||
0xc0000: 0x80400040,
|
||||
0xd0000: 0x1040,
|
||||
0xe0000: 0x1000,
|
||||
0xf0000: 0x80401040,
|
||||
0x8000: 0x80001040,
|
||||
0x18000: 0x40,
|
||||
0x28000: 0x80400040,
|
||||
0x38000: 0x80001000,
|
||||
0x48000: 0x401000,
|
||||
0x58000: 0x80401040,
|
||||
0x68000: 0x0,
|
||||
0x78000: 0x80400000,
|
||||
0x88000: 0x1000,
|
||||
0x98000: 0x80401000,
|
||||
0xa8000: 0x400000,
|
||||
0xb8000: 0x1040,
|
||||
0xc8000: 0x80000000,
|
||||
0xd8000: 0x400040,
|
||||
0xe8000: 0x401040,
|
||||
0xf8000: 0x80000040,
|
||||
0x100000: 0x400040,
|
||||
0x110000: 0x401000,
|
||||
0x120000: 0x80000040,
|
||||
0x130000: 0x0,
|
||||
0x140000: 0x1040,
|
||||
0x150000: 0x80400040,
|
||||
0x160000: 0x80401000,
|
||||
0x170000: 0x80001040,
|
||||
0x180000: 0x80401040,
|
||||
0x190000: 0x80000000,
|
||||
0x1a0000: 0x80400000,
|
||||
0x1b0000: 0x401040,
|
||||
0x1c0000: 0x80001000,
|
||||
0x1d0000: 0x400000,
|
||||
0x1e0000: 0x40,
|
||||
0x1f0000: 0x1000,
|
||||
0x108000: 0x80400000,
|
||||
0x118000: 0x80401040,
|
||||
0x128000: 0x0,
|
||||
0x138000: 0x401000,
|
||||
0x148000: 0x400040,
|
||||
0x158000: 0x80000000,
|
||||
0x168000: 0x80001040,
|
||||
0x178000: 0x40,
|
||||
0x188000: 0x80000040,
|
||||
0x198000: 0x1000,
|
||||
0x1a8000: 0x80001000,
|
||||
0x1b8000: 0x80400040,
|
||||
0x1c8000: 0x1040,
|
||||
0x1d8000: 0x80401000,
|
||||
0x1e8000: 0x400000,
|
||||
0x1f8000: 0x401040,
|
||||
},
|
||||
{
|
||||
0x0: 0x80,
|
||||
0x1000: 0x1040000,
|
||||
0x2000: 0x40000,
|
||||
0x3000: 0x20000000,
|
||||
0x4000: 0x20040080,
|
||||
0x5000: 0x1000080,
|
||||
0x6000: 0x21000080,
|
||||
0x7000: 0x40080,
|
||||
0x8000: 0x1000000,
|
||||
0x9000: 0x20040000,
|
||||
0xa000: 0x20000080,
|
||||
0xb000: 0x21040080,
|
||||
0xc000: 0x21040000,
|
||||
0xd000: 0x0,
|
||||
0xe000: 0x1040080,
|
||||
0xf000: 0x21000000,
|
||||
0x800: 0x1040080,
|
||||
0x1800: 0x21000080,
|
||||
0x2800: 0x80,
|
||||
0x3800: 0x1040000,
|
||||
0x4800: 0x40000,
|
||||
0x5800: 0x20040080,
|
||||
0x6800: 0x21040000,
|
||||
0x7800: 0x20000000,
|
||||
0x8800: 0x20040000,
|
||||
0x9800: 0x0,
|
||||
0xa800: 0x21040080,
|
||||
0xb800: 0x1000080,
|
||||
0xc800: 0x20000080,
|
||||
0xd800: 0x21000000,
|
||||
0xe800: 0x1000000,
|
||||
0xf800: 0x40080,
|
||||
0x10000: 0x40000,
|
||||
0x11000: 0x80,
|
||||
0x12000: 0x20000000,
|
||||
0x13000: 0x21000080,
|
||||
0x14000: 0x1000080,
|
||||
0x15000: 0x21040000,
|
||||
0x16000: 0x20040080,
|
||||
0x17000: 0x1000000,
|
||||
0x18000: 0x21040080,
|
||||
0x19000: 0x21000000,
|
||||
0x1a000: 0x1040000,
|
||||
0x1b000: 0x20040000,
|
||||
0x1c000: 0x40080,
|
||||
0x1d000: 0x20000080,
|
||||
0x1e000: 0x0,
|
||||
0x1f000: 0x1040080,
|
||||
0x10800: 0x21000080,
|
||||
0x11800: 0x1000000,
|
||||
0x12800: 0x1040000,
|
||||
0x13800: 0x20040080,
|
||||
0x14800: 0x20000000,
|
||||
0x15800: 0x1040080,
|
||||
0x16800: 0x80,
|
||||
0x17800: 0x21040000,
|
||||
0x18800: 0x40080,
|
||||
0x19800: 0x21040080,
|
||||
0x1a800: 0x0,
|
||||
0x1b800: 0x21000000,
|
||||
0x1c800: 0x1000080,
|
||||
0x1d800: 0x40000,
|
||||
0x1e800: 0x20040000,
|
||||
0x1f800: 0x20000080,
|
||||
},
|
||||
{
|
||||
0x0: 0x10000008,
|
||||
0x100: 0x2000,
|
||||
0x200: 0x10200000,
|
||||
0x300: 0x10202008,
|
||||
0x400: 0x10002000,
|
||||
0x500: 0x200000,
|
||||
0x600: 0x200008,
|
||||
0x700: 0x10000000,
|
||||
0x800: 0x0,
|
||||
0x900: 0x10002008,
|
||||
0xa00: 0x202000,
|
||||
0xb00: 0x8,
|
||||
0xc00: 0x10200008,
|
||||
0xd00: 0x202008,
|
||||
0xe00: 0x2008,
|
||||
0xf00: 0x10202000,
|
||||
0x80: 0x10200000,
|
||||
0x180: 0x10202008,
|
||||
0x280: 0x8,
|
||||
0x380: 0x200000,
|
||||
0x480: 0x202008,
|
||||
0x580: 0x10000008,
|
||||
0x680: 0x10002000,
|
||||
0x780: 0x2008,
|
||||
0x880: 0x200008,
|
||||
0x980: 0x2000,
|
||||
0xa80: 0x10002008,
|
||||
0xb80: 0x10200008,
|
||||
0xc80: 0x0,
|
||||
0xd80: 0x10202000,
|
||||
0xe80: 0x202000,
|
||||
0xf80: 0x10000000,
|
||||
0x1000: 0x10002000,
|
||||
0x1100: 0x10200008,
|
||||
0x1200: 0x10202008,
|
||||
0x1300: 0x2008,
|
||||
0x1400: 0x200000,
|
||||
0x1500: 0x10000000,
|
||||
0x1600: 0x10000008,
|
||||
0x1700: 0x202000,
|
||||
0x1800: 0x202008,
|
||||
0x1900: 0x0,
|
||||
0x1a00: 0x8,
|
||||
0x1b00: 0x10200000,
|
||||
0x1c00: 0x2000,
|
||||
0x1d00: 0x10002008,
|
||||
0x1e00: 0x10202000,
|
||||
0x1f00: 0x200008,
|
||||
0x1080: 0x8,
|
||||
0x1180: 0x202000,
|
||||
0x1280: 0x200000,
|
||||
0x1380: 0x10000008,
|
||||
0x1480: 0x10002000,
|
||||
0x1580: 0x2008,
|
||||
0x1680: 0x10202008,
|
||||
0x1780: 0x10200000,
|
||||
0x1880: 0x10202000,
|
||||
0x1980: 0x10200008,
|
||||
0x1a80: 0x2000,
|
||||
0x1b80: 0x202008,
|
||||
0x1c80: 0x200008,
|
||||
0x1d80: 0x0,
|
||||
0x1e80: 0x10000000,
|
||||
0x1f80: 0x10002008,
|
||||
},
|
||||
{
|
||||
0x0: 0x100000,
|
||||
0x10: 0x2000401,
|
||||
0x20: 0x400,
|
||||
0x30: 0x100401,
|
||||
0x40: 0x2100401,
|
||||
0x50: 0x0,
|
||||
0x60: 0x1,
|
||||
0x70: 0x2100001,
|
||||
0x80: 0x2000400,
|
||||
0x90: 0x100001,
|
||||
0xa0: 0x2000001,
|
||||
0xb0: 0x2100400,
|
||||
0xc0: 0x2100000,
|
||||
0xd0: 0x401,
|
||||
0xe0: 0x100400,
|
||||
0xf0: 0x2000000,
|
||||
0x8: 0x2100001,
|
||||
0x18: 0x0,
|
||||
0x28: 0x2000401,
|
||||
0x38: 0x2100400,
|
||||
0x48: 0x100000,
|
||||
0x58: 0x2000001,
|
||||
0x68: 0x2000000,
|
||||
0x78: 0x401,
|
||||
0x88: 0x100401,
|
||||
0x98: 0x2000400,
|
||||
0xa8: 0x2100000,
|
||||
0xb8: 0x100001,
|
||||
0xc8: 0x400,
|
||||
0xd8: 0x2100401,
|
||||
0xe8: 0x1,
|
||||
0xf8: 0x100400,
|
||||
0x100: 0x2000000,
|
||||
0x110: 0x100000,
|
||||
0x120: 0x2000401,
|
||||
0x130: 0x2100001,
|
||||
0x140: 0x100001,
|
||||
0x150: 0x2000400,
|
||||
0x160: 0x2100400,
|
||||
0x170: 0x100401,
|
||||
0x180: 0x401,
|
||||
0x190: 0x2100401,
|
||||
0x1a0: 0x100400,
|
||||
0x1b0: 0x1,
|
||||
0x1c0: 0x0,
|
||||
0x1d0: 0x2100000,
|
||||
0x1e0: 0x2000001,
|
||||
0x1f0: 0x400,
|
||||
0x108: 0x100400,
|
||||
0x118: 0x2000401,
|
||||
0x128: 0x2100001,
|
||||
0x138: 0x1,
|
||||
0x148: 0x2000000,
|
||||
0x158: 0x100000,
|
||||
0x168: 0x401,
|
||||
0x178: 0x2100400,
|
||||
0x188: 0x2000001,
|
||||
0x198: 0x2100000,
|
||||
0x1a8: 0x0,
|
||||
0x1b8: 0x2100401,
|
||||
0x1c8: 0x100401,
|
||||
0x1d8: 0x400,
|
||||
0x1e8: 0x2000400,
|
||||
0x1f8: 0x100001,
|
||||
},
|
||||
{
|
||||
0x0: 0x8000820,
|
||||
0x1: 0x20000,
|
||||
0x2: 0x8000000,
|
||||
0x3: 0x20,
|
||||
0x4: 0x20020,
|
||||
0x5: 0x8020820,
|
||||
0x6: 0x8020800,
|
||||
0x7: 0x800,
|
||||
0x8: 0x8020000,
|
||||
0x9: 0x8000800,
|
||||
0xa: 0x20800,
|
||||
0xb: 0x8020020,
|
||||
0xc: 0x820,
|
||||
0xd: 0x0,
|
||||
0xe: 0x8000020,
|
||||
0xf: 0x20820,
|
||||
0x80000000: 0x800,
|
||||
0x80000001: 0x8020820,
|
||||
0x80000002: 0x8000820,
|
||||
0x80000003: 0x8000000,
|
||||
0x80000004: 0x8020000,
|
||||
0x80000005: 0x20800,
|
||||
0x80000006: 0x20820,
|
||||
0x80000007: 0x20,
|
||||
0x80000008: 0x8000020,
|
||||
0x80000009: 0x820,
|
||||
0x8000000a: 0x20020,
|
||||
0x8000000b: 0x8020800,
|
||||
0x8000000c: 0x0,
|
||||
0x8000000d: 0x8020020,
|
||||
0x8000000e: 0x8000800,
|
||||
0x8000000f: 0x20000,
|
||||
0x10: 0x20820,
|
||||
0x11: 0x8020800,
|
||||
0x12: 0x20,
|
||||
0x13: 0x800,
|
||||
0x14: 0x8000800,
|
||||
0x15: 0x8000020,
|
||||
0x16: 0x8020020,
|
||||
0x17: 0x20000,
|
||||
0x18: 0x0,
|
||||
0x19: 0x20020,
|
||||
0x1a: 0x8020000,
|
||||
0x1b: 0x8000820,
|
||||
0x1c: 0x8020820,
|
||||
0x1d: 0x20800,
|
||||
0x1e: 0x820,
|
||||
0x1f: 0x8000000,
|
||||
0x80000010: 0x20000,
|
||||
0x80000011: 0x800,
|
||||
0x80000012: 0x8020020,
|
||||
0x80000013: 0x20820,
|
||||
0x80000014: 0x20,
|
||||
0x80000015: 0x8020000,
|
||||
0x80000016: 0x8000000,
|
||||
0x80000017: 0x8000820,
|
||||
0x80000018: 0x8020820,
|
||||
0x80000019: 0x8000020,
|
||||
0x8000001a: 0x8000800,
|
||||
0x8000001b: 0x0,
|
||||
0x8000001c: 0x20800,
|
||||
0x8000001d: 0x820,
|
||||
0x8000001e: 0x20020,
|
||||
0x8000001f: 0x8020800,
|
||||
},
|
||||
];
|
||||
|
||||
// Masks that select the SBOX input
|
||||
const SBOX_MASK = [
|
||||
0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000,
|
||||
0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f,
|
||||
];
|
||||
|
||||
// Swap bits across the left and right words
|
||||
function exchangeLR(offset, mask) {
|
||||
const t = ((this._lBlock >>> offset) ^ this._rBlock) & mask;
|
||||
this._rBlock ^= t;
|
||||
this._lBlock ^= t << offset;
|
||||
}
|
||||
|
||||
function exchangeRL(offset, mask) {
|
||||
const t = ((this._rBlock >>> offset) ^ this._lBlock) & mask;
|
||||
this._lBlock ^= t;
|
||||
this._rBlock ^= t << offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* DES block cipher algorithm.
|
||||
*/
|
||||
export class DESAlgo extends BlockCipher {
|
||||
constructor(xformMode, key, cfg) {
|
||||
super(xformMode, key, cfg);
|
||||
|
||||
// blickSize is an instance field and should set in constructor.
|
||||
// Both DESAlgo and TripleDESAlgo.
|
||||
this.blockSize = 64 / 32;
|
||||
}
|
||||
|
||||
_doReset() {
|
||||
// Shortcuts
|
||||
const key = this._key;
|
||||
const keyWords = key.words;
|
||||
|
||||
// Select 56 bits according to PC1
|
||||
const keyBits = [];
|
||||
for (let i = 0; i < 56; i += 1) {
|
||||
const keyBitPos = PC1[i] - 1;
|
||||
keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - (keyBitPos % 32))) & 1;
|
||||
}
|
||||
|
||||
// Assemble 16 subkeys
|
||||
this._subKeys = [];
|
||||
const subKeys = this._subKeys;
|
||||
for (let nSubKey = 0; nSubKey < 16; nSubKey += 1) {
|
||||
// Create subkey
|
||||
subKeys[nSubKey] = [];
|
||||
const subKey = subKeys[nSubKey];
|
||||
|
||||
// Shortcut
|
||||
const bitShift = BIT_SHIFTS[nSubKey];
|
||||
|
||||
// Select 48 bits according to PC2
|
||||
for (let i = 0; i < 24; i += 1) {
|
||||
// Select from the left 28 key bits
|
||||
subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - (i % 6));
|
||||
|
||||
// Select from the right 28 key bits
|
||||
subKey[4 + ((i / 6) | 0)]
|
||||
|= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)]
|
||||
<< (31 - (i % 6));
|
||||
}
|
||||
|
||||
// Since each subkey is applied to an expanded 32-bit input,
|
||||
// the subkey can be broken into 8 values scaled to 32-bits,
|
||||
// which allows the key to be used without expansion
|
||||
subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31);
|
||||
for (let i = 1; i < 7; i += 1) {
|
||||
subKey[i] >>>= ((i - 1) * 4 + 3);
|
||||
}
|
||||
subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27);
|
||||
}
|
||||
|
||||
// Compute inverse subkeys
|
||||
this._invSubKeys = [];
|
||||
const invSubKeys = this._invSubKeys;
|
||||
for (let i = 0; i < 16; i += 1) {
|
||||
invSubKeys[i] = subKeys[15 - i];
|
||||
}
|
||||
}
|
||||
|
||||
encryptBlock(M, offset) {
|
||||
this._doCryptBlock(M, offset, this._subKeys);
|
||||
}
|
||||
|
||||
decryptBlock(M, offset) {
|
||||
this._doCryptBlock(M, offset, this._invSubKeys);
|
||||
}
|
||||
|
||||
_doCryptBlock(M, offset, subKeys) {
|
||||
const _M = M;
|
||||
|
||||
// Get input
|
||||
this._lBlock = M[offset];
|
||||
this._rBlock = M[offset + 1];
|
||||
|
||||
// Initial permutation
|
||||
exchangeLR.call(this, 4, 0x0f0f0f0f);
|
||||
exchangeLR.call(this, 16, 0x0000ffff);
|
||||
exchangeRL.call(this, 2, 0x33333333);
|
||||
exchangeRL.call(this, 8, 0x00ff00ff);
|
||||
exchangeLR.call(this, 1, 0x55555555);
|
||||
|
||||
// Rounds
|
||||
for (let round = 0; round < 16; round += 1) {
|
||||
// Shortcuts
|
||||
const subKey = subKeys[round];
|
||||
const lBlock = this._lBlock;
|
||||
const rBlock = this._rBlock;
|
||||
|
||||
// Feistel function
|
||||
let f = 0;
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0];
|
||||
}
|
||||
this._lBlock = rBlock;
|
||||
this._rBlock = lBlock ^ f;
|
||||
}
|
||||
|
||||
// Undo swap from last round
|
||||
const t = this._lBlock;
|
||||
this._lBlock = this._rBlock;
|
||||
this._rBlock = t;
|
||||
|
||||
// Final permutation
|
||||
exchangeLR.call(this, 1, 0x55555555);
|
||||
exchangeRL.call(this, 8, 0x00ff00ff);
|
||||
exchangeRL.call(this, 2, 0x33333333);
|
||||
exchangeLR.call(this, 16, 0x0000ffff);
|
||||
exchangeLR.call(this, 4, 0x0f0f0f0f);
|
||||
|
||||
// Set output
|
||||
_M[offset] = this._lBlock;
|
||||
_M[offset + 1] = this._rBlock;
|
||||
}
|
||||
}
|
||||
DESAlgo.keySize = 64 / 32;
|
||||
DESAlgo.ivSize = 64 / 32;
|
||||
// blickSize is an instance field and should set in constructor.
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.DES.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const DES = BlockCipher._createHelper(DESAlgo);
|
||||
|
||||
/**
|
||||
* Triple-DES block cipher algorithm.
|
||||
*/
|
||||
export class TripleDESAlgo extends BlockCipher {
|
||||
_doReset() {
|
||||
// Shortcuts
|
||||
const key = this._key;
|
||||
const keyWords = key.words;
|
||||
// Make sure the key length is valid (64, 128 or >= 192 bit)
|
||||
if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) {
|
||||
throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.');
|
||||
}
|
||||
|
||||
// Extend the key according to the keying options defined in 3DES standard
|
||||
const key1 = keyWords.slice(0, 2);
|
||||
const key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4);
|
||||
const key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6);
|
||||
|
||||
// Create DES instances
|
||||
this._des1 = DESAlgo.createEncryptor(WordArray.create(key1));
|
||||
this._des2 = DESAlgo.createEncryptor(WordArray.create(key2));
|
||||
this._des3 = DESAlgo.createEncryptor(WordArray.create(key3));
|
||||
}
|
||||
|
||||
encryptBlock(M, offset) {
|
||||
this._des1.encryptBlock(M, offset);
|
||||
this._des2.decryptBlock(M, offset);
|
||||
this._des3.encryptBlock(M, offset);
|
||||
}
|
||||
|
||||
decryptBlock(M, offset) {
|
||||
this._des3.decryptBlock(M, offset);
|
||||
this._des2.encryptBlock(M, offset);
|
||||
this._des1.decryptBlock(M, offset);
|
||||
}
|
||||
}
|
||||
TripleDESAlgo.keySize = 192 / 32;
|
||||
TripleDESAlgo.ivSize = 64 / 32;
|
||||
// blickSize is an instance field and should set in constructor.
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
export const TripleDES = BlockCipher._createHelper(TripleDESAlgo);
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* A 64-bit word.
|
||||
*/
|
||||
export class X64Word extends Base {
|
||||
/**
|
||||
* Initializes a newly created 64-bit word.
|
||||
*
|
||||
* @param {number} high The high 32 bits.
|
||||
* @param {number} low The low 32 bits.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607);
|
||||
*/
|
||||
static create(high: number, low: number): X64Word;
|
||||
constructor(high: number, low: number);
|
||||
high: number;
|
||||
low: number;
|
||||
}
|
||||
/**
|
||||
* An array of 64-bit words.
|
||||
*
|
||||
* @property {Array} words The array of CryptoJS.x64.Word objects.
|
||||
* @property {number} sigBytes The number of significant bytes in this word array.
|
||||
*/
|
||||
export class X64WordArray extends Base {
|
||||
/**
|
||||
* Initializes a newly created word array.
|
||||
*
|
||||
* @param {Array} words (Optional) An array of CryptoJS.x64.Word objects.
|
||||
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.x64.WordArray.create();
|
||||
*
|
||||
* var wordArray = CryptoJS.x64.WordArray.create([
|
||||
* CryptoJS.x64.Word.create(0x00010203, 0x04050607),
|
||||
* CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
|
||||
* ]);
|
||||
*
|
||||
* var wordArray = CryptoJS.x64.WordArray.create([
|
||||
* CryptoJS.x64.Word.create(0x00010203, 0x04050607),
|
||||
* CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
|
||||
* ], 10);
|
||||
*/
|
||||
static create(words?: Array<X64Word>, sigBytes?: number): X64WordArray;
|
||||
constructor(words?: Array<X64Word>, sigBytes?: number);
|
||||
words: X64Word[];
|
||||
sigBytes: number;
|
||||
/**
|
||||
* Converts this 64-bit word array to a 32-bit word array.
|
||||
*
|
||||
* @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var x32WordArray = x64WordArray.toX32();
|
||||
*/
|
||||
toX32(): WordArray;
|
||||
/**
|
||||
* Creates a copy of this word array.
|
||||
*
|
||||
* @return {X64WordArray} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = x64WordArray.clone();
|
||||
*/
|
||||
clone(): X64WordArray;
|
||||
}
|
||||
import { Base } from './core.js';
|
||||
import { WordArray } from './core.js';
|
||||
@@ -0,0 +1,113 @@
|
||||
import {
|
||||
Base,
|
||||
WordArray,
|
||||
} from './core.js';
|
||||
|
||||
const X32WordArray = WordArray;
|
||||
|
||||
/**
|
||||
* A 64-bit word.
|
||||
*/
|
||||
export class X64Word extends Base {
|
||||
/**
|
||||
* Initializes a newly created 64-bit word.
|
||||
*
|
||||
* @param {number} high The high 32 bits.
|
||||
* @param {number} low The low 32 bits.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607);
|
||||
*/
|
||||
constructor(high, low) {
|
||||
super();
|
||||
|
||||
this.high = high;
|
||||
this.low = low;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of 64-bit words.
|
||||
*
|
||||
* @property {Array} words The array of CryptoJS.x64.Word objects.
|
||||
* @property {number} sigBytes The number of significant bytes in this word array.
|
||||
*/
|
||||
export class X64WordArray extends Base {
|
||||
/**
|
||||
* Initializes a newly created word array.
|
||||
*
|
||||
* @param {Array} words (Optional) An array of CryptoJS.x64.Word objects.
|
||||
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.x64.WordArray.create();
|
||||
*
|
||||
* var wordArray = CryptoJS.x64.WordArray.create([
|
||||
* CryptoJS.x64.Word.create(0x00010203, 0x04050607),
|
||||
* CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
|
||||
* ]);
|
||||
*
|
||||
* var wordArray = CryptoJS.x64.WordArray.create([
|
||||
* CryptoJS.x64.Word.create(0x00010203, 0x04050607),
|
||||
* CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
|
||||
* ], 10);
|
||||
*/
|
||||
constructor(words = [], sigBytes = words.length * 8) {
|
||||
super();
|
||||
|
||||
this.words = words;
|
||||
this.sigBytes = sigBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this 64-bit word array to a 32-bit word array.
|
||||
*
|
||||
* @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var x32WordArray = x64WordArray.toX32();
|
||||
*/
|
||||
toX32() {
|
||||
// Shortcuts
|
||||
const x64Words = this.words;
|
||||
const x64WordsLength = x64Words.length;
|
||||
|
||||
// Convert
|
||||
const x32Words = [];
|
||||
for (let i = 0; i < x64WordsLength; i += 1) {
|
||||
const x64Word = x64Words[i];
|
||||
x32Words.push(x64Word.high);
|
||||
x32Words.push(x64Word.low);
|
||||
}
|
||||
|
||||
return X32WordArray.create(x32Words, this.sigBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this word array.
|
||||
*
|
||||
* @return {X64WordArray} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = x64WordArray.clone();
|
||||
*/
|
||||
clone() {
|
||||
const clone = super.clone.call(this);
|
||||
|
||||
// Clone "words" array
|
||||
clone.words = this.words.slice(0);
|
||||
const { words } = clone;
|
||||
|
||||
// Clone each X64Word object
|
||||
const wordsLength = words.length;
|
||||
for (let i = 0; i < wordsLength; i += 1) {
|
||||
words[i] = words[i].clone();
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
import { b64tohex, hex2b64 } from "./lib/jsbn/base64";
|
||||
import { JSEncryptRSAKey } from "./JSEncryptRSAKey";
|
||||
const version = typeof process !== 'undefined'
|
||||
? process.env?.npm_package_version
|
||||
: undefined;
|
||||
|
||||
export interface IJSEncryptOptions {
|
||||
default_key_size?: string;
|
||||
default_public_exponent?: string;
|
||||
log?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Object} [options = {}] - An object to customize JSEncrypt behaviour
|
||||
* possible parameters are:
|
||||
* - default_key_size {number} default: 1024 the key size in bit
|
||||
* - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent
|
||||
* - log {boolean} default: false whether log warn/error or not
|
||||
* @constructor
|
||||
*/
|
||||
export class JSEncrypt {
|
||||
constructor(options: IJSEncryptOptions = {}) {
|
||||
options = options || {};
|
||||
this.default_key_size = options.default_key_size
|
||||
? parseInt(options.default_key_size, 10)
|
||||
: 1024;
|
||||
this.default_public_exponent = options.default_public_exponent || "010001"; // 65537 default openssl public exponent for rsa key type
|
||||
this.log = options.log || false;
|
||||
// The private and public key.
|
||||
this.key = null;
|
||||
}
|
||||
|
||||
private default_key_size: number;
|
||||
private default_public_exponent: string;
|
||||
private log: boolean;
|
||||
private key: JSEncryptRSAKey;
|
||||
public static version: string = version;
|
||||
|
||||
/**
|
||||
* Method to set the rsa key parameter (one method is enough to set both the public
|
||||
* and the private key, since the private key contains the public key paramenters)
|
||||
* Log a warning if logs are enabled
|
||||
* @param {Object|string} key the pem encoded string or an object (with or without header/footer)
|
||||
* @public
|
||||
*/
|
||||
public setKey(key: string) {
|
||||
if (this.log && this.key) {
|
||||
console.warn("A key was already set, overriding existing.");
|
||||
}
|
||||
this.key = new JSEncryptRSAKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method for setKey, for api compatibility
|
||||
* @see setKey
|
||||
* @public
|
||||
*/
|
||||
public setPrivateKey(privkey: string) {
|
||||
// Create the key.
|
||||
this.setKey(privkey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method for setKey, for api compatibility
|
||||
* @see setKey
|
||||
* @public
|
||||
*/
|
||||
public setPublicKey(pubkey: string) {
|
||||
// Sets the public key.
|
||||
this.setKey(pubkey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method for RSAKey object's decrypt, decrypt the string using the private
|
||||
* components of the rsa key object. Note that if the object was not set will be created
|
||||
* on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
|
||||
* @param {string} str base64 encoded crypted string to decrypt
|
||||
* @return {string} the decrypted string
|
||||
* @public
|
||||
*/
|
||||
public decrypt(str: string) {
|
||||
// Return the decrypted string.
|
||||
try {
|
||||
return this.getKey().decrypt(b64tohex(str));
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method for RSAKey object's encrypt, encrypt the string using the public
|
||||
* components of the rsa key object. Note that if the object was not set will be created
|
||||
* on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
|
||||
* @param {string} str the string to encrypt
|
||||
* @return {string} the encrypted string encoded in base64
|
||||
* @public
|
||||
*/
|
||||
public encrypt(str: string) {
|
||||
// Return the encrypted string.
|
||||
try {
|
||||
return hex2b64(this.getKey().encrypt(str));
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method for RSAKey object's sign.
|
||||
* @param {string} str the string to sign
|
||||
* @param {function} digestMethod hash method
|
||||
* @param {string} digestName the name of the hash algorithm
|
||||
* @return {string} the signature encoded in base64
|
||||
* @public
|
||||
*/
|
||||
public sign(
|
||||
str: string,
|
||||
digestMethod: (str: string) => string,
|
||||
digestName: string,
|
||||
): string | false {
|
||||
// return the RSA signature of 'str' in 'hex' format.
|
||||
try {
|
||||
return hex2b64(this.getKey().sign(str, digestMethod, digestName));
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method for RSAKey object's verify.
|
||||
* @param {string} str the string to verify
|
||||
* @param {string} signature the signature encoded in base64 to compare the string to
|
||||
* @param {function} digestMethod hash method
|
||||
* @return {boolean} whether the data and signature match
|
||||
* @public
|
||||
*/
|
||||
public verify(
|
||||
str: string,
|
||||
signature: string,
|
||||
digestMethod: (str: string) => string,
|
||||
): boolean {
|
||||
// Return the decrypted 'digest' of the signature.
|
||||
try {
|
||||
return this.getKey().verify(str, b64tohex(signature), digestMethod);
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object
|
||||
* will be created and returned
|
||||
* @param {callback} [cb] the callback to be called if we want the key to be generated
|
||||
* in an async fashion
|
||||
* @returns {JSEncryptRSAKey} the JSEncryptRSAKey object
|
||||
* @public
|
||||
*/
|
||||
public getKey(cb?: () => void) {
|
||||
// Only create new if it does not exist.
|
||||
if (!this.key) {
|
||||
// Get a new private key.
|
||||
this.key = new JSEncryptRSAKey();
|
||||
if (cb && {}.toString.call(cb) === "[object Function]") {
|
||||
this.key.generateAsync(
|
||||
this.default_key_size,
|
||||
this.default_public_exponent,
|
||||
cb,
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Generate the key.
|
||||
this.key.generate(this.default_key_size, this.default_public_exponent);
|
||||
}
|
||||
return this.key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pem encoded representation of the private key
|
||||
* If the key doesn't exists a new key will be created
|
||||
* @returns {string} pem encoded representation of the private key WITH header and footer
|
||||
* @public
|
||||
*/
|
||||
public getPrivateKey() {
|
||||
// Return the private representation of this key.
|
||||
return this.getKey().getPrivateKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pem encoded representation of the private key
|
||||
* If the key doesn't exists a new key will be created
|
||||
* @returns {string} pem encoded representation of the private key WITHOUT header and footer
|
||||
* @public
|
||||
*/
|
||||
public getPrivateKeyB64() {
|
||||
// Return the private representation of this key.
|
||||
return this.getKey().getPrivateBaseKeyB64();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pem encoded representation of the public key
|
||||
* If the key doesn't exists a new key will be created
|
||||
* @returns {string} pem encoded representation of the public key WITH header and footer
|
||||
* @public
|
||||
*/
|
||||
public getPublicKey() {
|
||||
// Return the private representation of this key.
|
||||
return this.getKey().getPublicKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pem encoded representation of the public key
|
||||
* If the key doesn't exists a new key will be created
|
||||
* @returns {string} pem encoded representation of the public key WITHOUT header and footer
|
||||
* @public
|
||||
*/
|
||||
public getPublicKeyB64() {
|
||||
// Return the private representation of this key.
|
||||
return this.getKey().getPublicBaseKeyB64();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
import { hex2b64 } from "./lib/jsbn/base64";
|
||||
import { Hex } from "./lib/asn1js/hex";
|
||||
import { Base64 } from "./lib/asn1js/base64";
|
||||
import { ASN1 } from "./lib/asn1js/asn1";
|
||||
import { RSAKey } from "./lib/jsbn/rsa";
|
||||
import { parseBigInt } from "./lib/jsbn/jsbn";
|
||||
import { KJUR } from "./lib/jsrsasign/asn1-1.0";
|
||||
|
||||
/**
|
||||
* Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object.
|
||||
* This object is just a decorator for parsing the key parameter
|
||||
* @param {string|Object} key - The key in string format, or an object containing
|
||||
* the parameters needed to build a RSAKey object.
|
||||
* @constructor
|
||||
*/
|
||||
export class JSEncryptRSAKey extends RSAKey {
|
||||
constructor(key?: string) {
|
||||
super();
|
||||
// Call the super constructor.
|
||||
// RSAKey.call(this);
|
||||
// If a key key was provided.
|
||||
if (key) {
|
||||
// If this is a string...
|
||||
if (typeof key === "string") {
|
||||
this.parseKey(key);
|
||||
} else if (
|
||||
JSEncryptRSAKey.hasPrivateKeyProperty(key) ||
|
||||
JSEncryptRSAKey.hasPublicKeyProperty(key)
|
||||
) {
|
||||
// Set the values for the key.
|
||||
this.parsePropertiesFrom(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to parse a pem encoded string containing both a public or private key.
|
||||
* The method will translate the pem encoded string in a der encoded string and
|
||||
* will parse private key and public key parameters. This method accepts public key
|
||||
* in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).
|
||||
*
|
||||
* @todo Check how many rsa formats use the same format of pkcs #1.
|
||||
*
|
||||
* The format is defined as:
|
||||
* PublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* PublicKey BIT STRING
|
||||
* }
|
||||
* Where AlgorithmIdentifier is:
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
|
||||
* }
|
||||
* and PublicKey is a SEQUENCE encapsulated in a BIT STRING
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER -- e
|
||||
* }
|
||||
* it's possible to examine the structure of the keys obtained from openssl using
|
||||
* an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/
|
||||
* @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer
|
||||
* @private
|
||||
*/
|
||||
public parseKey(pem: string) {
|
||||
try {
|
||||
let modulus: string | number = 0;
|
||||
let public_exponent: string | number = 0;
|
||||
const reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/;
|
||||
const der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
|
||||
let asn1 = ASN1.decode(der);
|
||||
|
||||
// Fixes a bug with OpenSSL 1.0+ private keys
|
||||
if (asn1.sub.length === 3) {
|
||||
asn1 = asn1.sub[2].sub[0];
|
||||
}
|
||||
if (asn1.sub.length === 9) {
|
||||
// Parse the private key.
|
||||
modulus = asn1.sub[1].getHexStringValue(); // bigint
|
||||
this.n = parseBigInt(modulus, 16);
|
||||
|
||||
public_exponent = asn1.sub[2].getHexStringValue(); // int
|
||||
this.e = parseInt(public_exponent, 16);
|
||||
|
||||
const private_exponent = asn1.sub[3].getHexStringValue(); // bigint
|
||||
this.d = parseBigInt(private_exponent, 16);
|
||||
|
||||
const prime1 = asn1.sub[4].getHexStringValue(); // bigint
|
||||
this.p = parseBigInt(prime1, 16);
|
||||
|
||||
const prime2 = asn1.sub[5].getHexStringValue(); // bigint
|
||||
this.q = parseBigInt(prime2, 16);
|
||||
|
||||
const exponent1 = asn1.sub[6].getHexStringValue(); // bigint
|
||||
this.dmp1 = parseBigInt(exponent1, 16);
|
||||
|
||||
const exponent2 = asn1.sub[7].getHexStringValue(); // bigint
|
||||
this.dmq1 = parseBigInt(exponent2, 16);
|
||||
|
||||
const coefficient = asn1.sub[8].getHexStringValue(); // bigint
|
||||
this.coeff = parseBigInt(coefficient, 16);
|
||||
} else if (asn1.sub.length === 2) {
|
||||
if (asn1.sub[0].sub) {
|
||||
// Parse ASN.1 SubjectPublicKeyInfo type as defined by X.509
|
||||
var bit_string = asn1.sub[1];
|
||||
var sequence = bit_string.sub[0];
|
||||
modulus = sequence.sub[0].getHexStringValue();
|
||||
this.n = parseBigInt(modulus, 16);
|
||||
public_exponent = sequence.sub[1].getHexStringValue();
|
||||
this.e = parseInt(public_exponent, 16);
|
||||
} else {
|
||||
// Parse ASN.1 RSAPublicKey type as defined by PKCS #1
|
||||
modulus = asn1.sub[0].getHexStringValue();
|
||||
this.n = parseBigInt(modulus, 16);
|
||||
public_exponent = asn1.sub[1].getHexStringValue();
|
||||
this.e = parseInt(public_exponent, 16);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate rsa parameters in a hex encoded string representing the rsa key.
|
||||
*
|
||||
* The translation follow the ASN.1 notation :
|
||||
* RSAPrivateKey ::= SEQUENCE {
|
||||
* version Version,
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER, -- e
|
||||
* privateExponent INTEGER, -- d
|
||||
* prime1 INTEGER, -- p
|
||||
* prime2 INTEGER, -- q
|
||||
* exponent1 INTEGER, -- d mod (p1)
|
||||
* exponent2 INTEGER, -- d mod (q-1)
|
||||
* coefficient INTEGER, -- (inverse of q) mod p
|
||||
* }
|
||||
* @returns {string} DER Encoded String representing the rsa private key
|
||||
* @private
|
||||
*/
|
||||
public getPrivateBaseKey() {
|
||||
const options = {
|
||||
array: [
|
||||
new KJUR.asn1.DERInteger({ int: 0 }),
|
||||
new KJUR.asn1.DERInteger({ bigint: this.n }),
|
||||
new KJUR.asn1.DERInteger({ int: this.e }),
|
||||
new KJUR.asn1.DERInteger({ bigint: this.d }),
|
||||
new KJUR.asn1.DERInteger({ bigint: this.p }),
|
||||
new KJUR.asn1.DERInteger({ bigint: this.q }),
|
||||
new KJUR.asn1.DERInteger({ bigint: this.dmp1 }),
|
||||
new KJUR.asn1.DERInteger({ bigint: this.dmq1 }),
|
||||
new KJUR.asn1.DERInteger({ bigint: this.coeff }),
|
||||
],
|
||||
};
|
||||
const seq = new KJUR.asn1.DERSequence(options);
|
||||
return seq.getEncodedHex();
|
||||
}
|
||||
|
||||
/**
|
||||
* base64 (pem) encoded version of the DER encoded representation
|
||||
* @returns {string} pem encoded representation without header and footer
|
||||
* @public
|
||||
*/
|
||||
public getPrivateBaseKeyB64() {
|
||||
return hex2b64(this.getPrivateBaseKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate rsa parameters in a hex encoded string representing the rsa public key.
|
||||
* The representation follow the ASN.1 notation :
|
||||
* PublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* PublicKey BIT STRING
|
||||
* }
|
||||
* Where AlgorithmIdentifier is:
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
|
||||
* }
|
||||
* and PublicKey is a SEQUENCE encapsulated in a BIT STRING
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER -- e
|
||||
* }
|
||||
* @returns {string} DER Encoded String representing the rsa public key
|
||||
* @private
|
||||
*/
|
||||
public getPublicBaseKey() {
|
||||
const first_sequence = new KJUR.asn1.DERSequence({
|
||||
array: [
|
||||
new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.1.1" }), // RSA Encryption pkcs #1 oid
|
||||
new KJUR.asn1.DERNull(),
|
||||
],
|
||||
});
|
||||
|
||||
const second_sequence = new KJUR.asn1.DERSequence({
|
||||
array: [
|
||||
new KJUR.asn1.DERInteger({ bigint: this.n }),
|
||||
new KJUR.asn1.DERInteger({ int: this.e }),
|
||||
],
|
||||
});
|
||||
|
||||
const bit_string = new KJUR.asn1.DERBitString({
|
||||
hex: "00" + second_sequence.getEncodedHex(),
|
||||
});
|
||||
|
||||
const seq = new KJUR.asn1.DERSequence({
|
||||
array: [first_sequence, bit_string],
|
||||
});
|
||||
return seq.getEncodedHex();
|
||||
}
|
||||
|
||||
/**
|
||||
* base64 (pem) encoded version of the DER encoded representation
|
||||
* @returns {string} pem encoded representation without header and footer
|
||||
* @public
|
||||
*/
|
||||
public getPublicBaseKeyB64() {
|
||||
return hex2b64(this.getPublicBaseKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* wrap the string in block of width chars. The default value for rsa keys is 64
|
||||
* characters.
|
||||
* @param {string} str the pem encoded string without header and footer
|
||||
* @param {Number} [width=64] - the length the string has to be wrapped at
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
public static wordwrap(str: string, width?: number) {
|
||||
width = width || 64;
|
||||
if (!str) {
|
||||
return str;
|
||||
}
|
||||
const regex = "(.{1," + width + "})( +|$\n?)|(.{1," + width + "})";
|
||||
return str.match(RegExp(regex, "g")).join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the pem encoded private key
|
||||
* @returns {string} the pem encoded private key with header/footer
|
||||
* @public
|
||||
*/
|
||||
public getPrivateKey() {
|
||||
let key = "-----BEGIN RSA PRIVATE KEY-----\n";
|
||||
key += JSEncryptRSAKey.wordwrap(this.getPrivateBaseKeyB64()) + "\n";
|
||||
key += "-----END RSA PRIVATE KEY-----";
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the pem encoded public key
|
||||
* @returns {string} the pem encoded public key with header/footer
|
||||
* @public
|
||||
*/
|
||||
public getPublicKey() {
|
||||
let key = "-----BEGIN PUBLIC KEY-----\n";
|
||||
key += JSEncryptRSAKey.wordwrap(this.getPublicBaseKeyB64()) + "\n";
|
||||
key += "-----END PUBLIC KEY-----";
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the object contains the necessary parameters to populate the rsa modulus
|
||||
* and public exponent parameters.
|
||||
* @param {Object} [obj={}] - An object that may contain the two public key
|
||||
* parameters
|
||||
* @returns {boolean} true if the object contains both the modulus and the public exponent
|
||||
* properties (n and e)
|
||||
* @todo check for types of n and e. N should be a parseable bigInt object, E should
|
||||
* be a parseable integer number
|
||||
* @private
|
||||
*/
|
||||
public static hasPublicKeyProperty(obj: object) {
|
||||
obj = obj || {};
|
||||
return obj.hasOwnProperty("n") && obj.hasOwnProperty("e");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the object contains ALL the parameters of an RSA key.
|
||||
* @param {Object} [obj={}] - An object that may contain nine rsa key
|
||||
* parameters
|
||||
* @returns {boolean} true if the object contains all the parameters needed
|
||||
* @todo check for types of the parameters all the parameters but the public exponent
|
||||
* should be parseable bigint objects, the public exponent should be a parseable integer number
|
||||
* @private
|
||||
*/
|
||||
public static hasPrivateKeyProperty(obj: object) {
|
||||
obj = obj || {};
|
||||
return (
|
||||
obj.hasOwnProperty("n") &&
|
||||
obj.hasOwnProperty("e") &&
|
||||
obj.hasOwnProperty("d") &&
|
||||
obj.hasOwnProperty("p") &&
|
||||
obj.hasOwnProperty("q") &&
|
||||
obj.hasOwnProperty("dmp1") &&
|
||||
obj.hasOwnProperty("dmq1") &&
|
||||
obj.hasOwnProperty("coeff")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the properties of obj in the current rsa object. Obj should AT LEAST
|
||||
* include the modulus and public exponent (n, e) parameters.
|
||||
* @param {Object} obj - the object containing rsa parameters
|
||||
* @private
|
||||
*/
|
||||
public parsePropertiesFrom(obj: any) {
|
||||
this.n = obj.n;
|
||||
this.e = obj.e;
|
||||
|
||||
if (obj.hasOwnProperty("d")) {
|
||||
this.d = obj.d;
|
||||
this.p = obj.p;
|
||||
this.q = obj.q;
|
||||
this.dmp1 = obj.dmp1;
|
||||
this.dmq1 = obj.dmq1;
|
||||
this.coeff = obj.coeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2015 Form.io
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,3 @@
|
||||
import { JSEncrypt } from './JSEncrypt';
|
||||
export { JSEncrypt }
|
||||
export default JSEncrypt;
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
|
||||
ASN.1 JavaScript decoder
|
||||
Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -0,0 +1,598 @@
|
||||
// ASN.1 JavaScript decoder
|
||||
// Copyright (c) 2008-2014 Lapo Luchini <lapo@lapo.it>
|
||||
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
||||
/*global oids */
|
||||
|
||||
import {Int10} from "./int10";
|
||||
|
||||
const ellipsis = "\u2026";
|
||||
const reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
|
||||
const reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
|
||||
|
||||
function stringCut(str:string, len:number) {
|
||||
if (str.length > len) {
|
||||
str = str.substring(0, len) + ellipsis;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
export class Stream {
|
||||
constructor(enc:Stream|number[], pos?:number) {
|
||||
if (enc instanceof Stream) {
|
||||
this.enc = enc.enc;
|
||||
this.pos = enc.pos;
|
||||
} else {
|
||||
// enc should be an array or a binary string
|
||||
this.enc = enc;
|
||||
this.pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
private enc:string|number[];
|
||||
public pos:number;
|
||||
|
||||
public get(pos?:number) {
|
||||
if (pos === undefined) {
|
||||
pos = this.pos++;
|
||||
}
|
||||
if (pos >= this.enc.length) {
|
||||
throw new Error(`Requesting byte offset ${pos} on a stream of length ${this.enc.length}`);
|
||||
}
|
||||
return ("string" === typeof this.enc) ? this.enc.charCodeAt(pos) : this.enc[pos];
|
||||
}
|
||||
|
||||
public hexDigits = "0123456789ABCDEF";
|
||||
|
||||
public hexByte(b:number) {
|
||||
return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF);
|
||||
}
|
||||
|
||||
public hexDump(start:number, end:number, raw:boolean) {
|
||||
let s = "";
|
||||
for (let i = start; i < end; ++i) {
|
||||
s += this.hexByte(this.get(i));
|
||||
if (raw !== true) {
|
||||
switch (i & 0xF) {
|
||||
case 0x7:
|
||||
s += " ";
|
||||
break;
|
||||
case 0xF:
|
||||
s += "\n";
|
||||
break;
|
||||
default:
|
||||
s += " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public isASCII(start:number, end:number) {
|
||||
for (let i = start; i < end; ++i) {
|
||||
const c = this.get(i);
|
||||
if (c < 32 || c > 176) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public parseStringISO(start:number, end:number) {
|
||||
let s = "";
|
||||
for (let i = start; i < end; ++i) {
|
||||
s += String.fromCharCode(this.get(i));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public parseStringUTF(start:number, end:number) {
|
||||
let s = "";
|
||||
for (let i = start; i < end;) {
|
||||
const c = this.get(i++);
|
||||
if (c < 128) {
|
||||
s += String.fromCharCode(c);
|
||||
} else if ((c > 191) && (c < 224)) {
|
||||
s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F));
|
||||
} else {
|
||||
s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public parseStringBMP(start:number, end:number) {
|
||||
let str = "";
|
||||
let hi;
|
||||
let lo;
|
||||
for (let i = start; i < end;) {
|
||||
hi = this.get(i++);
|
||||
lo = this.get(i++);
|
||||
str += String.fromCharCode((hi << 8) | lo);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public parseTime(start:number, end:number, shortYear:boolean) {
|
||||
let s = this.parseStringISO(start, end);
|
||||
const m:Array<number|string> = (shortYear ? reTimeS : reTimeL).exec(s);
|
||||
if (!m) {
|
||||
return "Unrecognized time: " + s;
|
||||
}
|
||||
if (shortYear) {
|
||||
// to avoid querying the timer, use the fixed range [1970, 2069]
|
||||
// it will conform with ITU X.400 [-10, +40] sliding window until 2030
|
||||
m[1] = +m[1];
|
||||
(m[1] as number) += (+m[1] < 70) ? 2000 : 1900;
|
||||
}
|
||||
s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4];
|
||||
if (m[5]) {
|
||||
s += ":" + m[5];
|
||||
if (m[6]) {
|
||||
s += ":" + m[6];
|
||||
if (m[7]) {
|
||||
s += "." + m[7];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m[8]) {
|
||||
s += " UTC";
|
||||
if (m[8] != "Z") {
|
||||
s += m[8];
|
||||
if (m[9]) {
|
||||
s += ":" + m[9];
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public parseInteger(start:number, end:number) {
|
||||
let v = this.get(start);
|
||||
const neg = (v > 127);
|
||||
const pad = neg ? 255 : 0;
|
||||
let len;
|
||||
let s:string | number = "";
|
||||
// skip unuseful bits (not allowed in DER)
|
||||
while (v == pad && ++start < end) {
|
||||
v = this.get(start);
|
||||
}
|
||||
len = end - start;
|
||||
if (len === 0) {
|
||||
return neg ? -1 : 0;
|
||||
}
|
||||
// show bit length of huge integers
|
||||
if (len > 4) {
|
||||
s = v;
|
||||
len <<= 3;
|
||||
while (((+s ^ pad) & 0x80) == 0) {
|
||||
s = +s << 1;
|
||||
--len;
|
||||
}
|
||||
s = "(" + len + " bit)\n";
|
||||
}
|
||||
// decode the integer
|
||||
if (neg) {
|
||||
v = v - 256;
|
||||
}
|
||||
const n = new Int10(v);
|
||||
for (let i = start + 1; i < end; ++i) {
|
||||
n.mulAdd(256, this.get(i));
|
||||
}
|
||||
return s + n.toString();
|
||||
}
|
||||
|
||||
public parseBitString(start:number, end:number, maxLength:number) {
|
||||
const unusedBit = this.get(start);
|
||||
const lenBit = ((end - start - 1) << 3) - unusedBit;
|
||||
const intro = "(" + lenBit + " bit)\n";
|
||||
let s = "";
|
||||
for (let i = start + 1; i < end; ++i) {
|
||||
const b = this.get(i);
|
||||
const skip = (i == end - 1) ? unusedBit : 0;
|
||||
for (let j = 7; j >= skip; --j) {
|
||||
s += (b >> j) & 1 ? "1" : "0";
|
||||
}
|
||||
if (s.length > maxLength) {
|
||||
return intro + stringCut(s, maxLength);
|
||||
}
|
||||
}
|
||||
return intro + s;
|
||||
}
|
||||
|
||||
public parseOctetString(start:number, end:number, maxLength:number) {
|
||||
if (this.isASCII(start, end)) {
|
||||
return stringCut(this.parseStringISO(start, end), maxLength);
|
||||
}
|
||||
const len = end - start;
|
||||
let s = "(" + len + " byte)\n";
|
||||
maxLength /= 2; // we work in bytes
|
||||
if (len > maxLength) {
|
||||
end = start + maxLength;
|
||||
}
|
||||
for (let i = start; i < end; ++i) {
|
||||
s += this.hexByte(this.get(i));
|
||||
}
|
||||
if (len > maxLength) {
|
||||
s += ellipsis;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public parseOID(start:number, end:number, maxLength:number) {
|
||||
let s = "";
|
||||
let n:number|Int10 = new Int10();
|
||||
let bits = 0;
|
||||
for (let i = start; i < end; ++i) {
|
||||
const v = this.get(i);
|
||||
n.mulAdd(128, v & 0x7F);
|
||||
bits += 7;
|
||||
if (!(v & 0x80)) { // finished
|
||||
if (s === "") {
|
||||
n = n.simplify();
|
||||
if (n instanceof Int10) {
|
||||
n.sub(80);
|
||||
s = "2." + n.toString();
|
||||
} else {
|
||||
const m = n < 80 ? n < 40 ? 0 : 1 : 2;
|
||||
s = m + "." + (n - m * 40);
|
||||
}
|
||||
} else {
|
||||
s += "." + n.toString();
|
||||
}
|
||||
if (s.length > maxLength) {
|
||||
return stringCut(s, maxLength);
|
||||
}
|
||||
n = new Int10();
|
||||
bits = 0;
|
||||
}
|
||||
}
|
||||
if (bits > 0) {
|
||||
s += ".incomplete";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
export class ASN1 {
|
||||
constructor(stream:Stream, header:number, length:number, tag:ASN1Tag, sub:ASN1[]) {
|
||||
if (!(tag instanceof ASN1Tag)) {
|
||||
throw new Error("Invalid tag value.");
|
||||
}
|
||||
this.stream = stream;
|
||||
this.header = header;
|
||||
this.length = length;
|
||||
this.tag = tag;
|
||||
this.sub = sub;
|
||||
}
|
||||
|
||||
private stream:Stream;
|
||||
private header:number;
|
||||
private length:number;
|
||||
private tag:ASN1Tag;
|
||||
public sub:ASN1[];
|
||||
|
||||
public typeName() {
|
||||
switch (this.tag.tagClass) {
|
||||
case 0: // universal
|
||||
switch (this.tag.tagNumber) {
|
||||
case 0x00:
|
||||
return "EOC";
|
||||
case 0x01:
|
||||
return "BOOLEAN";
|
||||
case 0x02:
|
||||
return "INTEGER";
|
||||
case 0x03:
|
||||
return "BIT_STRING";
|
||||
case 0x04:
|
||||
return "OCTET_STRING";
|
||||
case 0x05:
|
||||
return "NULL";
|
||||
case 0x06:
|
||||
return "OBJECT_IDENTIFIER";
|
||||
case 0x07:
|
||||
return "ObjectDescriptor";
|
||||
case 0x08:
|
||||
return "EXTERNAL";
|
||||
case 0x09:
|
||||
return "REAL";
|
||||
case 0x0A:
|
||||
return "ENUMERATED";
|
||||
case 0x0B:
|
||||
return "EMBEDDED_PDV";
|
||||
case 0x0C:
|
||||
return "UTF8String";
|
||||
case 0x10:
|
||||
return "SEQUENCE";
|
||||
case 0x11:
|
||||
return "SET";
|
||||
case 0x12:
|
||||
return "NumericString";
|
||||
case 0x13:
|
||||
return "PrintableString"; // ASCII subset
|
||||
case 0x14:
|
||||
return "TeletexString"; // aka T61String
|
||||
case 0x15:
|
||||
return "VideotexString";
|
||||
case 0x16:
|
||||
return "IA5String"; // ASCII
|
||||
case 0x17:
|
||||
return "UTCTime";
|
||||
case 0x18:
|
||||
return "GeneralizedTime";
|
||||
case 0x19:
|
||||
return "GraphicString";
|
||||
case 0x1A:
|
||||
return "VisibleString"; // ASCII subset
|
||||
case 0x1B:
|
||||
return "GeneralString";
|
||||
case 0x1C:
|
||||
return "UniversalString";
|
||||
case 0x1E:
|
||||
return "BMPString";
|
||||
}
|
||||
return "Universal_" + this.tag.tagNumber.toString();
|
||||
case 1:
|
||||
return "Application_" + this.tag.tagNumber.toString();
|
||||
case 2:
|
||||
return "[" + this.tag.tagNumber.toString() + "]"; // Context
|
||||
case 3:
|
||||
return "Private_" + this.tag.tagNumber.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public content(maxLength:number) { // a preview of the content (intended for humans)
|
||||
if (this.tag === undefined) {
|
||||
return null;
|
||||
}
|
||||
if (maxLength === undefined) {
|
||||
maxLength = Infinity;
|
||||
}
|
||||
const content = this.posContent();
|
||||
const len = Math.abs(this.length);
|
||||
if (!this.tag.isUniversal()) {
|
||||
if (this.sub !== null) {
|
||||
return "(" + this.sub.length + " elem)";
|
||||
}
|
||||
return this.stream.parseOctetString(content, content + len, maxLength);
|
||||
}
|
||||
switch (this.tag.tagNumber) {
|
||||
case 0x01: // BOOLEAN
|
||||
return (this.stream.get(content) === 0) ? "false" : "true";
|
||||
case 0x02: // INTEGER
|
||||
return this.stream.parseInteger(content, content + len);
|
||||
case 0x03: // BIT_STRING
|
||||
return this.sub ? "(" + this.sub.length + " elem)" :
|
||||
this.stream.parseBitString(content, content + len, maxLength);
|
||||
case 0x04: // OCTET_STRING
|
||||
return this.sub ? "(" + this.sub.length + " elem)" :
|
||||
this.stream.parseOctetString(content, content + len, maxLength);
|
||||
// case 0x05: // NULL
|
||||
case 0x06: // OBJECT_IDENTIFIER
|
||||
return this.stream.parseOID(content, content + len, maxLength);
|
||||
// case 0x07: // ObjectDescriptor
|
||||
// case 0x08: // EXTERNAL
|
||||
// case 0x09: // REAL
|
||||
// case 0x0A: // ENUMERATED
|
||||
// case 0x0B: // EMBEDDED_PDV
|
||||
case 0x10: // SEQUENCE
|
||||
case 0x11: // SET
|
||||
if (this.sub !== null) {
|
||||
return "(" + this.sub.length + " elem)";
|
||||
} else {
|
||||
return "(no elem)";
|
||||
}
|
||||
case 0x0C: // UTF8String
|
||||
return stringCut(this.stream.parseStringUTF(content, content + len), maxLength);
|
||||
case 0x12: // NumericString
|
||||
case 0x13: // PrintableString
|
||||
case 0x14: // TeletexString
|
||||
case 0x15: // VideotexString
|
||||
case 0x16: // IA5String
|
||||
// case 0x19: // GraphicString
|
||||
case 0x1A: // VisibleString
|
||||
// case 0x1B: // GeneralString
|
||||
// case 0x1C: // UniversalString
|
||||
return stringCut(this.stream.parseStringISO(content, content + len), maxLength);
|
||||
case 0x1E: // BMPString
|
||||
return stringCut(this.stream.parseStringBMP(content, content + len), maxLength);
|
||||
case 0x17: // UTCTime
|
||||
case 0x18: // GeneralizedTime
|
||||
return this.stream.parseTime(content, content + len, (this.tag.tagNumber == 0x17));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public toString() {
|
||||
return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.sub === null) ? "null" : this.sub.length) + "]";
|
||||
}
|
||||
|
||||
public toPrettyString(indent:string) {
|
||||
if (indent === undefined) {
|
||||
indent = "";
|
||||
}
|
||||
let s = indent + this.typeName() + " @" + this.stream.pos;
|
||||
if (this.length >= 0) {
|
||||
s += "+";
|
||||
}
|
||||
s += this.length;
|
||||
if (this.tag.tagConstructed) {
|
||||
s += " (constructed)";
|
||||
} else if ((this.tag.isUniversal() && ((this.tag.tagNumber == 0x03) || (this.tag.tagNumber == 0x04))) && (this.sub !== null)) {
|
||||
s += " (encapsulates)";
|
||||
}
|
||||
s += "\n";
|
||||
if (this.sub !== null) {
|
||||
indent += " ";
|
||||
for (let i = 0, max = this.sub.length; i < max; ++i) {
|
||||
s += this.sub[i].toPrettyString(indent);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public posStart() {
|
||||
return this.stream.pos;
|
||||
}
|
||||
|
||||
public posContent() {
|
||||
return this.stream.pos + this.header;
|
||||
}
|
||||
|
||||
public posEnd() {
|
||||
return this.stream.pos + this.header + Math.abs(this.length);
|
||||
}
|
||||
|
||||
public toHexString() {
|
||||
return this.stream.hexDump(this.posStart(), this.posEnd(), true);
|
||||
}
|
||||
|
||||
public static decodeLength(stream:Stream):number {
|
||||
let buf = stream.get();
|
||||
const len = buf & 0x7F;
|
||||
if (len == buf) {
|
||||
return len;
|
||||
}
|
||||
|
||||
// no reason to use Int10, as it would be a huge buffer anyways
|
||||
if (len > 6) {
|
||||
throw new Error("Length over 48 bits not supported at position " + (stream.pos - 1));
|
||||
}
|
||||
if (len === 0) {
|
||||
return null;
|
||||
} // undefined
|
||||
buf = 0;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
buf = (buf * 256) + stream.get();
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the hexadecimal value (as a string) of the current ASN.1 element
|
||||
* @returns {string}
|
||||
* @public
|
||||
*/
|
||||
public getHexStringValue():string {
|
||||
const hexString = this.toHexString();
|
||||
const offset = this.header * 2;
|
||||
const length = this.length * 2;
|
||||
return hexString.substr(offset, length);
|
||||
}
|
||||
|
||||
public static decode(str:Stream|number[]) {
|
||||
let stream:Stream;
|
||||
|
||||
if (!(str instanceof Stream)) {
|
||||
stream = new Stream(str, 0);
|
||||
} else {
|
||||
stream = str;
|
||||
}
|
||||
|
||||
const streamStart = new Stream(stream);
|
||||
const tag = new ASN1Tag(stream);
|
||||
let len = ASN1.decodeLength(stream);
|
||||
const start = stream.pos;
|
||||
const header = start - streamStart.pos;
|
||||
let sub = null;
|
||||
const getSub:() => ASN1[] = function () {
|
||||
const ret = [];
|
||||
if (len !== null) {
|
||||
// definite length
|
||||
const end = start + len;
|
||||
while (stream.pos < end) {
|
||||
ret[ret.length] = ASN1.decode(stream);
|
||||
}
|
||||
if (stream.pos != end) {
|
||||
throw new Error("Content size is not correct for container starting at offset " + start);
|
||||
}
|
||||
} else {
|
||||
// undefined length
|
||||
try {
|
||||
for (; ;) {
|
||||
const s = ASN1.decode(stream);
|
||||
if (s.tag.isEOC()) {
|
||||
break;
|
||||
}
|
||||
ret[ret.length] = s;
|
||||
}
|
||||
len = start - stream.pos; // undefined lengths are represented as negative values
|
||||
} catch (e) {
|
||||
throw new Error("Exception while decoding undefined length content: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
if (tag.tagConstructed) {
|
||||
// must have valid content
|
||||
sub = getSub();
|
||||
} else if (tag.isUniversal() && ((tag.tagNumber == 0x03) || (tag.tagNumber == 0x04))) {
|
||||
// sometimes BitString and OctetString are used to encapsulate ASN.1
|
||||
try {
|
||||
if (tag.tagNumber == 0x03) {
|
||||
if (stream.get() != 0) {
|
||||
throw new Error("BIT STRINGs with unused bits cannot encapsulate.");
|
||||
}
|
||||
}
|
||||
sub = getSub();
|
||||
for (let i = 0; i < sub.length; ++i) {
|
||||
if (sub[i].tag.isEOC()) {
|
||||
throw new Error("EOC is not supposed to be actual content.");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// but silently ignore when they don't
|
||||
sub = null;
|
||||
}
|
||||
}
|
||||
if (sub === null) {
|
||||
if (len === null) {
|
||||
throw new Error("We can't skip over an invalid tag with undefined length at offset " + start);
|
||||
}
|
||||
stream.pos = start + Math.abs(len);
|
||||
}
|
||||
return new ASN1(streamStart, header, len, tag, sub);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ASN1Tag {
|
||||
constructor(stream:Stream) {
|
||||
let buf = stream.get();
|
||||
this.tagClass = buf >> 6;
|
||||
this.tagConstructed = ((buf & 0x20) !== 0);
|
||||
this.tagNumber = buf & 0x1F;
|
||||
if (this.tagNumber == 0x1F) { // long tag
|
||||
const n = new Int10();
|
||||
do {
|
||||
buf = stream.get();
|
||||
n.mulAdd(128, buf & 0x7F);
|
||||
} while (buf & 0x80);
|
||||
this.tagNumber = n.simplify();
|
||||
}
|
||||
}
|
||||
|
||||
public tagClass:number;
|
||||
public tagConstructed:boolean;
|
||||
public tagNumber:number | Int10;
|
||||
|
||||
public isUniversal() {
|
||||
return this.tagClass === 0x00;
|
||||
}
|
||||
|
||||
public isEOC() {
|
||||
return this.tagClass === 0x00 && this.tagNumber === 0x00;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Base64 JavaScript decoder
|
||||
// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
||||
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
||||
let decoder:{ [index:string]:number | string };
|
||||
export const Base64 = {
|
||||
decode(a:string) {
|
||||
let i;
|
||||
if (decoder === undefined) {
|
||||
const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
const ignore = "= \f\n\r\t\u00A0\u2028\u2029";
|
||||
decoder = Object.create(null);
|
||||
for (i = 0; i < 64; ++i) {
|
||||
decoder[b64.charAt(i)] = i;
|
||||
}
|
||||
decoder['-'] = 62;//+
|
||||
decoder['_'] = 63;//-
|
||||
for (i = 0; i < ignore.length; ++i) {
|
||||
decoder[ignore.charAt(i)] = -1;
|
||||
}
|
||||
}
|
||||
const out = [];
|
||||
let bits = 0;
|
||||
let char_count = 0;
|
||||
for (i = 0; i < a.length; ++i) {
|
||||
let c:string|number = a.charAt(i);
|
||||
if (c == "=") {
|
||||
break;
|
||||
}
|
||||
c = decoder[c];
|
||||
if (c == -1) {
|
||||
continue;
|
||||
}
|
||||
if (c === undefined) {
|
||||
throw new Error("Illegal character at offset " + i);
|
||||
}
|
||||
bits |= c as number;
|
||||
if (++char_count >= 4) {
|
||||
out[out.length] = (bits >> 16);
|
||||
out[out.length] = (bits >> 8) & 0xFF;
|
||||
out[out.length] = bits & 0xFF;
|
||||
bits = 0;
|
||||
char_count = 0;
|
||||
} else {
|
||||
bits <<= 6;
|
||||
}
|
||||
}
|
||||
switch (char_count) {
|
||||
case 1:
|
||||
throw new Error("Base64 encoding incomplete: at least 2 bits missing");
|
||||
case 2:
|
||||
out[out.length] = (bits >> 10);
|
||||
break;
|
||||
case 3:
|
||||
out[out.length] = (bits >> 16);
|
||||
out[out.length] = (bits >> 8) & 0xFF;
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
re: /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,
|
||||
unarmor(a:string):number[] {
|
||||
const m = Base64.re.exec(a);
|
||||
if (m) {
|
||||
if (m[1]) {
|
||||
a = m[1];
|
||||
} else if (m[2]) {
|
||||
a = m[2];
|
||||
} else {
|
||||
throw new Error("RegExp out of sync");
|
||||
}
|
||||
}
|
||||
return Base64.decode(a);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
// Hex JavaScript decoder
|
||||
// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
||||
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
||||
|
||||
let decoder:{ [index:string]:number };
|
||||
export const Hex = {
|
||||
decode(a:string):number[] {
|
||||
let i;
|
||||
if (decoder === undefined) {
|
||||
let hex = "0123456789ABCDEF";
|
||||
const ignore = " \f\n\r\t\u00A0\u2028\u2029";
|
||||
decoder = {};
|
||||
for (i = 0; i < 16; ++i) {
|
||||
decoder[hex.charAt(i)] = i;
|
||||
}
|
||||
hex = hex.toLowerCase();
|
||||
for (i = 10; i < 16; ++i) {
|
||||
decoder[hex.charAt(i)] = i;
|
||||
}
|
||||
for (i = 0; i < ignore.length; ++i) {
|
||||
decoder[ignore.charAt(i)] = -1;
|
||||
}
|
||||
}
|
||||
const out = [];
|
||||
let bits = 0;
|
||||
let char_count = 0;
|
||||
for (i = 0; i < a.length; ++i) {
|
||||
let c:number|string = a.charAt(i);
|
||||
if (c == "=") {
|
||||
break;
|
||||
}
|
||||
c = decoder[c];
|
||||
if (c == -1) {
|
||||
continue;
|
||||
}
|
||||
if (c === undefined) {
|
||||
throw new Error("Illegal character at offset " + i);
|
||||
}
|
||||
bits |= c;
|
||||
if (++char_count >= 2) {
|
||||
out[out.length] = bits;
|
||||
bits = 0;
|
||||
char_count = 0;
|
||||
} else {
|
||||
bits <<= 4;
|
||||
}
|
||||
}
|
||||
if (char_count) {
|
||||
throw new Error("Hex encoding incomplete: 4 bits missing");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
// Big integer base-10 printing library
|
||||
// Copyright (c) 2014 Lapo Luchini <lapo@lapo.it>
|
||||
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
||||
|
||||
|
||||
const max = 10000000000000; // biggest integer that can still fit 2^53 when multiplied by 256
|
||||
|
||||
export class Int10 {
|
||||
constructor(value?:string | number) {
|
||||
this.buf = [+value || 0];
|
||||
}
|
||||
|
||||
|
||||
public mulAdd(m:number, c:number) {
|
||||
// assert(m <= 256)
|
||||
const b = this.buf;
|
||||
const l = b.length;
|
||||
let i;
|
||||
let t;
|
||||
for (i = 0; i < l; ++i) {
|
||||
t = b[i] * m + c;
|
||||
if (t < max) {
|
||||
c = 0;
|
||||
} else {
|
||||
c = 0 | (t / max);
|
||||
t -= c * max;
|
||||
}
|
||||
b[i] = t;
|
||||
}
|
||||
if (c > 0) {
|
||||
b[i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
public sub(c:number) {
|
||||
// assert(m <= 256)
|
||||
const b = this.buf;
|
||||
const l = b.length;
|
||||
let i;
|
||||
let t;
|
||||
for (i = 0; i < l; ++i) {
|
||||
t = b[i] - c;
|
||||
if (t < 0) {
|
||||
t += max;
|
||||
c = 1;
|
||||
} else {
|
||||
c = 0;
|
||||
}
|
||||
b[i] = t;
|
||||
}
|
||||
while (b[b.length - 1] === 0) {
|
||||
b.pop();
|
||||
}
|
||||
}
|
||||
|
||||
public toString(base?:number) {
|
||||
if ((base || 10) != 10) {
|
||||
throw new Error("only base 10 is supported");
|
||||
}
|
||||
const b = this.buf;
|
||||
let s = b[b.length - 1].toString();
|
||||
for (let i = b.length - 2; i >= 0; --i) {
|
||||
s += (max + b[i]).toString().substring(1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public valueOf() {
|
||||
const b = this.buf;
|
||||
let v = 0;
|
||||
for (let i = b.length - 1; i >= 0; --i) {
|
||||
v = v * max + b[i];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
public simplify() {
|
||||
const b = this.buf;
|
||||
return (b.length == 1) ? b[0] : this;
|
||||
}
|
||||
|
||||
private buf:number[];
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
|
||||
|
||||
Licensing
|
||||
---------
|
||||
|
||||
This software is covered under the following copyright:
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003-2005 Tom Wu
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
|
||||
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* In addition, the following condition applies:
|
||||
*
|
||||
* All redistributions must retain an intact copy of this copyright notice
|
||||
* and disclaimer.
|
||||
*/
|
||||
|
||||
Address all questions regarding this license to:
|
||||
|
||||
Tom Wu
|
||||
tjw@cs.Stanford.EDU
|
||||
@@ -0,0 +1,6 @@
|
||||
These files are downloaded from http://www-cs-students.stanford.edu/~tjw/jsbn/
|
||||
|
||||
Here is a list of changes made to this library:
|
||||
|
||||
- https://github.com/travist/jsencrypt/pull/6
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import {int2char} from "./util";
|
||||
|
||||
const b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
const b64pad = "=";
|
||||
|
||||
export function hex2b64(h:string) {
|
||||
let i;
|
||||
let c;
|
||||
let ret = "";
|
||||
for (i = 0; i + 3 <= h.length; i += 3) {
|
||||
c = parseInt(h.substring(i, i + 3), 16);
|
||||
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
|
||||
}
|
||||
if (i + 1 == h.length) {
|
||||
c = parseInt(h.substring(i, i + 1), 16);
|
||||
ret += b64map.charAt(c << 2);
|
||||
} else if (i + 2 == h.length) {
|
||||
c = parseInt(h.substring(i, i + 2), 16);
|
||||
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
|
||||
}
|
||||
while ((ret.length & 3) > 0) {
|
||||
ret += b64pad;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// convert a base64 string to hex
|
||||
export function b64tohex(s:string) {
|
||||
let ret = "";
|
||||
let i;
|
||||
let k = 0; // b64 state, 0-3
|
||||
let slop = 0;
|
||||
for (i = 0; i < s.length; ++i) {
|
||||
if (s.charAt(i) == b64pad) {
|
||||
break;
|
||||
}
|
||||
const v = b64map.indexOf(s.charAt(i));
|
||||
if (v < 0) {
|
||||
continue;
|
||||
}
|
||||
if (k == 0) {
|
||||
ret += int2char(v >> 2);
|
||||
slop = v & 3;
|
||||
k = 1;
|
||||
} else if (k == 1) {
|
||||
ret += int2char((slop << 2) | (v >> 4));
|
||||
slop = v & 0xf;
|
||||
k = 2;
|
||||
} else if (k == 2) {
|
||||
ret += int2char(slop);
|
||||
ret += int2char(v >> 2);
|
||||
slop = v & 3;
|
||||
k = 3;
|
||||
} else {
|
||||
ret += int2char((slop << 2) | (v >> 4));
|
||||
ret += int2char(v & 0xf);
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
if (k == 1) {
|
||||
ret += int2char(slop << 2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// convert a base64 string to a byte/number array
|
||||
export function b64toBA(s:string) {
|
||||
// piggyback on b64tohex for now, optimize later
|
||||
const h = b64tohex(s);
|
||||
let i;
|
||||
const a = [];
|
||||
for (i = 0; 2 * i < h.length; ++i) {
|
||||
a[i] = parseInt(h.substring(2 * i, 2 * i + 2), 16);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user