加解密与消息摘要 - Crypto

# Crypto **[[Pro 8.0.0新增](https://pro.autojs.org/)]** $crypto模块提供了对称加密(例如AES)、非对称加密(例如RSA)、消息摘要(例如MD5, SHA)等支持。 ## $crypto.digest(message, algorithm[, options]) * `data` {any} 需要进行消息摘要的消息 * `key` {[Key](#key)} 解密密钥 * `algorithm` {string} 消息摘要算法,包括: * `MD5` * `SHA-1` * `SHA-224` * `SHA-256` * `SHA-384` * `SHA-512` 具体可参阅 [MessageDigest](https://developer.android.com/reference/java/security/MessageDigest) * `options` {Object} 可选项,用于指定[输入与输出的类型与格式](#输入与输出的类型与格式) * 返回 {any} 根据`options`指定的输出类型返回不同数据 对数据`data`用算法`algorithm`计算消息摘要,数据`data`可以是文件、二进制、base64、hex、字符串等数据,解密后数据可以返回二进制、base64、hex、字符串或者直接写入到文件中,具体参见[输入与输出的类型与格式](#输入与输出的类型与格式)。 ```javascript // 计算字符串abc的md5 console.log($crypto.digest("abc", "MD5")); // 计算字符串abc的sha-256 console.log($crypto.digest("abc", "SHA-256")); console.log($crypto.digest("Auto.js", "SHA-256", { input: "string", output: "hex" })); // 计算文件/sdcard/1.txt的md5 console.log($crypto.digest("/sdcard/1.txt", "MD5", { input: "file" })); ``` ## $crypto.encrypt(data, key, algorithm[, options]) * `data` {any} 明文消息,根据`options`指定的输入类型为不同格式的参数 * `key` {[Key](#key)} 加密密钥。对称加密算法使用单个密钥,非对称加密则需要生成密钥对,参见[Key](#key) * `algorithm` {string} 加密算法,包括: * AES * AES/ECB/NoPadding * AES/ECB/PKCS5Padding * AES/CBC/NoPadding * AES/CBC/PKCS5Padding * AES/CFB/NoPadding * AES/CFB/PKCS5Padding * AES/CTR/NoPadding * AES/CTR/PKCS5Padding * AES/OFB/PKCS5Padding * AES/OFB/PKCS5Padding * RSA/ECB/PKCS1Padding * RSA/ECB/NoPadding * ... 具体可参阅 [javax.crypto.Cipher](https://developer.android.com/reference/javax/crypto/Cipher) * `options` {Object} 可选项,用于指定[输入与输出的类型与格式](#输入与输出的类型与格式) * 返回 {any} 根据`options`指定的输出类型返回不同数据 使用密钥`key`对数据`data`用加密算法算法`algorithm`进行加密,数据`data`可以是文件、二进制、base64、hex、字符串等数据,加密后数据可以返回二进制、base64、hex、字符串或者直接写入到文件中,具体参见[输入与输出的类型与格式](#输入与输出的类型与格式)。 ```js let message = "Hello Autojs"; // 密钥,由于AES等算法要求是128/192/256 bits,我们这里长度为16, 即128bits let str16 = "a".repeat(16); let key = new $crypto.Key(str16); // AES toastLog($crypto.encrypt(message, key, "AES")); // [-18, 27, -69, 81, 2, -87, -116, 23, -114, -86, -111, 40, 58, -127, -29, -59] // AES输出结果用base64展示 toastLog( $crypto.encrypt(message, key, "AES", { output: "base64", }) ); // 7hu7UQKpjBeOqpEoOoHjxQ== // AES默认明文填充模式PKCS5Padding, 结果同上 toastLog( $crypto.encrypt(message, key, "AES/ECB/PKCS5Padding", { output: "base64", }) ); // 7hu7UQKpjBeOqpEoOoHjxQ== // AES加密 let cipherText = $crypto.encrypt(message, key, "AES"); toastLog(cipherText); // [-18, 27, -69, 81, 2, -87, -116, 23, -114, -86, -111, 40, 58, -127, -29, -59] // RSA256KeyPair let algorithm = "RSA"; let length = "2048"; // 生成RSA密钥对 key = $crypto.generateKeyPair(algorithm, length); let message = "Hello Autojs"; // RSA加密 cipherText = $crypto.encrypt(message, key.publicKey, "RSA/ECB/PKCS1Padding"); toastLog(cipherText); // [114, 99, -93, 6, -88, 8, -12, -53, -68, -15, ...] ``` ## $crypto.decrypt(data, key, algorithm[, options]) * `data` {any} 密文消息`options`指定的输入类型为不同格式的参数 * `key` {[Key](#key)} 解密密钥。对称加密算法使用单个密钥,非对称加密则需要生成密钥对,参见[Key](#key) * `algorithm` {string} 加密算法,包括: * AES * AES/ECB/NoPadding * AES/ECB/PKCS5Padding * AES/CBC/NoPadding * AES/CBC/PKCS5Padding * AES/CFB/NoPadding * AES/CFB/PKCS5Padding * AES/CTR/NoPadding * AES/CTR/PKCS5Padding * AES/OFB/PKCS5Padding * AES/OFB/PKCS5Padding * RSA/ECB/PKCS1Padding * RSA/ECB/NoPadding * ... 具体可参阅 [javax.crypto.Cipher](https://developer.android.com/reference/javax/crypto/Cipher) * `options` {Object} 可选项,用于指定[输入与输出的类型与格式](#输入与输出的类型与格式) * 返回 {any} 根据`options`指定的输出类型返回不同数据 使用密钥`key`对数据`data`用解密算法算法`algorithm`进行解密,数据`data`可以是文件、二进制、base64、hex、字符串等数据,解密后数据可以返回二进制、base64、hex、字符串或者直接写入到文件中,具体参见[输入与输出的类型与格式](#输入与输出的类型与格式)。 ```js // AES加密,加密为base64数据 let key = new $crypto.Key("123456790123456"); let cipherText = $crypto.encrypt("Hello, Auto.js Pro!", "AES", { input: "string", "output": "base64" }); // AES解密,将base64数据解密为字符串 let plaintext = $crypto.decrypt(cipherText, key, "AES", { "input": "base64", "output": "string" }); toastLog(plaintext); ``` ## $crypto.generateKeyPair(algorithm[, length]) * `algorithm` {string} 加密算法,包括 * `DH` * `DSA` * `EC` * `RSA` * `length` {number} 密钥长度。和算法相关,例如以位数指定的模数长度。默认为256。 * 返回 {[KeyPair](#keypair)} 生成一对密钥,包括公钥和私钥。例如在RSA加密算法中,我们可以用私钥加密,公钥解密做签名;或者公钥加密,私钥解密做数据加密。 ```js let keyPair = $crypto.generateKeyPair("RSA"); console.log("公钥为", keyPair.publicKey); console.log("私钥为", keyPair.privateKey); // 公钥加密、私钥解密 let plainText = "Hello World"; let bytes = $crypto.encrypt(plainText, keyPair.publicKey, "RSA"); let decryptedText = $crypto.decrypt(bytes, keyPair.privateKey, "RSA", { output: "string" }); console.log(decryptedText); // 公钥解密、私钥加密 let base64 = $crypto.encrypt(plainText, keyPair.privateKey, "RSA", { output: "base64" }); decryptedText = $crypto.decrypt(base64, keyPair.publicKey, "RSA", { input: "base64", output: "string" }); console.log(decryptedText); ``` # Key 密钥对象。可以直接通过构造函数构造。比如`new Key('12345678')`。 ## new Key(data[, options]) * `data` {any} 密钥的内容,根据`options`选项的输入格式而定,默认为字符串格式 * `options` {Object} 可选参数,参见[输入与输出的类型与格式](#输入与输出的类型与格式) 构造函数,构造一个Key对象。 ```js let key = new $crypto.Key('1234567890123456'); // 获取Key的二进制数据 let data = key.data; // 转换为base64 let base64 = android.util.Base64.encodeToString(data, android.util.Base64.NO_WRAP); // 从base64重新构造一个Key let copiedKey = new $crypto.Key(base64, {input: "base64"}); console.log(copiedKey.toString()); ``` ## Key.data * `byte[]` Key的二进制数据。 # KeyPair 密钥对对象。可以通过`$crypto.generateKeyPair()`函数生成,也可以通过构造函数构造。 ## new KeyPair(publicKey, privateKey[, options]) **[Pro 8.7.2新增]** * `publicKey` {any} 公钥的数据,根据`options`选项的输入格式而定,默认为字符串格式 * `privateKey` {any} 私钥的数据,根据`options`选项的输入格式而定,默认为字符串格式 * `options` {Object} 可选参数,参见[输入与输出的类型与格式](#输入与输出的类型与格式) 构造函数,构造一个KeyPair对象。 ```js let keyPair = $crypto.generateKeyPair("RSA"); // 获取公钥私钥的二进制数据,并转为base64 let data = { publicKey: base64Bytes(keyPair.publicKey.data), privateKey: base64Bytes(keyPair.privateKey.data), }; // 从base64重新构造一个Key let copiedKeyPair = new $crypto.KeyPair(data.publicKey, data.privateKey, {input: "base64"}); console.log(copiedKeyPair); function base64Bytes(bytes) { return android.util.Base64.encodeToString(bytes, android.util.Base64.NO_WRAP); } ``` ## KeyPair.privateKey * {[Key](#key)} 私钥。 ## KeyPair.publicKey * {[Key](#key)} 公钥。 # 输入与输出的类型与格式 `options` {object} 用于指定加解密、消息摘要时输入和输出的类型与格式。 * `input` {string} 输入类型,用于指定加密、解密、摘要的源数据的类型。如果输入为字符串,则默认为`string`;否则默认为`bytes`。可选的值包括: * `string` 字符串格式的数据 * `base64` base64格式的数据 * `hex` base16格式的数据 * `bytes` Java二进制字节数组 * `file` 文件类型,将从文件读取数据进行加解密 * `output` {string} 输出类型,用于指定加密、解密、摘要后的数据的类型。对于加解密,默认为`bytes`;对于消息摘要,默认为`hex`。可选的值包括: * `string` 字符串格式的数据 * `base64` base64格式的数据 * `hex` base16格式的数据 * `bytes` Java二进制字节数组 * `file` 文件类型,将处理后的数据写入到文件中,必须同时制定`dest`参数 * `dest` {string} 输出文件路径,`output`类型为`file`时,用于指定加密、解密、摘要后输出文件的路径 * `encoding` {string} 编码格式,`input`类型为`string`时,用于指定输入字符串转为二进制数据所使用的字符编码;`output`类型为`string`时,用于指定输出数据转为字符串数据所使用的字符编码。默认为`utf-8` ```js let filepath = files.join("./test.txt", "1.txt"); let message = "Hello Autojs"; $files.write(filepath, message); let str16 = "a".repeat(16); let key = new $crypto.Key(str16); // 创建加密前的base64内容 let base64Content = $base64.encode(key); // 加密前的hex内容 let hexContent = "48656c6c6f204175746f6a73"; // 加密文件,输出格式为二进制 console.log($crypto.encrypt(filepath, key, "AES", { input: "file", output: "base64" })); // 加密文件,输出到另一个文件 console.log($crypto.encrypt(filepath, key, "AES", { input: "file", output: "file", dest: "./output.txt" })); // 加密base64内容,输出格式为base64 console.log($crypto.encrypt("SGVsbG8gQXV0b2pz", key, "AES", { input: "base64", output: "base64" }); // 加密hex内容,输出格式为hex console.log($crypto.encrypt("48656c6c6f204175746f6a73", key, "AES", { input: "hex", output: "hex" })); console.log($crypto.encrypt("Hello Autojs", key, "AES")); // [-18, 27, -69, 81, 2, -87, -116, 23, -114, -86, -111, 40, 58, -127, -29, -59] // 计算文件MD5,输出为hex console.log($crypto.digest(filepath, "MD5", { input: "file", output: "hex" })); ```