跳至主要內容

crypto - 加解密与消息摘要

约 2067 字大约 7 分钟老猫

[Pro 8.0.0新增]

$crypto模块提供了对称加密(例如AES)、非对称加密(例如RSA)、消息摘要(例如MD5, SHA)等支持。

$crypto.digest(message, algorithm[, options])

  • data {any} 需要进行消息摘要的消息

  • key {Key} 解密密钥

  • algorithm {string} 消息摘要算法,包括:

  • options {Object} 可选项,用于指定输入与输出的类型与格式

  • 返回 {any} 根据options指定的输出类型返回不同数据

对数据data用算法algorithm计算消息摘要,数据data可以是文件、二进制、base64、hex、字符串等数据,解密后数据可以返回二进制、base64、hex、字符串或者直接写入到文件中,具体参见输入与输出的类型与格式

// 计算字符串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

  • 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.Cipheropen in new window
  • options {Object} 可选项,用于指定输入与输出的类型与格式

  • 返回 {any} 根据options指定的输出类型返回不同数据

使用密钥key对数据data用加密算法算法algorithm进行加密,数据data可以是文件、二进制、base64、hex、字符串等数据,加密后数据可以返回二进制、base64、hex、字符串或者直接写入到文件中,具体参见输入与输出的类型与格式

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

  • 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.Cipheropen in new window
  • options {Object} 可选项,用于指定输入与输出的类型与格式

  • 返回 {any} 根据options指定的输出类型返回不同数据

使用密钥key对数据data用解密算法算法algorithm进行解密,数据data可以是文件、二进制、base64、hex、字符串等数据,解密后数据可以返回二进制、base64、hex、字符串或者直接写入到文件中,具体参见输入与输出的类型与格式

// AES加密,加密为base64数据
let key = new $crypto.Key("1234567890123456");
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}

生成一对密钥,包括公钥和私钥。例如在RSA加密算法中,我们可以用私钥加密,公钥解密做签名;或者公钥加密,私钥解密做数据加密。

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对象。

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对象。

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

私钥。

KeyPair.publicKey

公钥。

输入与输出的类型与格式

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
  • iv {string} | {bytes} 指定AES等加密的初始化向量参数,可选。Pro 9.2.12版本新增。
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" \}));