概述
App Inventor 2没有内置加密组件,但可以通过以下方式实现文本加密:
| 方案 | 安全级别 | 实现方式 |
|---|---|---|
| Caesar密码(字符偏移) | ⭐ | 积木块直接实现 |
| XOR异或加密 | ⭐⭐ | 积木块实现 |
| Base64编码 | ⭐(非加密) | WebView/积木块 |
| SHA-256哈希 | ⭐⭐⭐(不可逆) | WebView |
| AES加密 | ⭐⭐⭐⭐⭐ | WebView + CryptoJS |
方案一:Caesar密码(凯撒密码)
最简单的加密方式,将每个字符偏移固定位数。
加密
function Caesar加密(原文, 偏移量) {
var 密文 = ""
var i = 1
while (i <= length(原文)) {
var 字符 = string_substring(原文, i, 1)
var ASCII码 = text_to_ascii(字符)
var 加密码 = ASCII码 + 偏移量
if (加密码 > 126) {
加密码 = 加密码 - 94 // 可打印ASCII范围
}
密文 = join(密文, ascii_to_text(加密码))
i = i + 1
}
return 密文
}
解密
function Caesar解密(密文, 偏移量) {
return Caesar加密(密文, 0 - 偏移量) // 反向偏移
}
使用示例
when 按钮_加密.Click() {
var 偏移量 = 输入框_偏移量.Text
var 加密结果 = Caesar加密(文本输入框_原文.Text, 偏移量)
标签_密文.Text = 加密结果
}
when 按钮_解密.Click() {
var 偏移量 = 输入框_偏移量.Text
var 解密结果 = Caesar解密(文本输入框_密文.Text, 偏移量)
标签_原文.Text = 解密结果
}
方案二:XOR异或加密
比Caesar更安全,使用密钥进行异或运算。
function XOR加密(原文, 密钥) {
var 密文 = ""
var 密钥长度 = length(密钥)
var i = 1
while (i <= length(原文)) {
var 原字符 = text_to_ascii(string_substring(原文, i, 1))
var 密钥字符 = text_to_ascii(string_substring(密钥, ((i-1) % 密钥长度) + 1, 1))
var 异或结果 = bitwise_xor(原字符, 密钥字符) // 使用位运算积木块
密文 = join(密文, text_to_hex(异或结果), " ")
i = i + 1
}
return 密文
}
function XOR解密(密文, 密钥) {
var 原文 = ""
var 十六进制列表 = split(密文, " ")
var 密钥长度 = length(密钥)
var i = 1
while (i <= length_of_list(十六进制列表)) {
var 加密字节 = hex_to_number(select_list_item(十六进制列表, i))
var 密钥字符 = text_to_ascii(string_substring(密钥, ((i-1) % 密钥长度) + 1, 1))
var 解密字节 = bitwise_xor(加密字节, 密钥字符)
原文 = join(原文, ascii_to_text(解密字节))
i = i + 1
}
return 原文
}
注意:XOR加密的特性是
加密(加密(原文, 密钥), 密钥) = 原文,即加密和解密用同一个函数。
方案三:Base64编码
Base64不是加密,只是编码转换,但可以隐藏明文内容。
使用WebView
when 按钮_Base64编码.Click() {
Web浏览器1.RunJavaScript(join("window.AppInventor.setWebViewString(btoa(unescape(encodeURIComponent('", 输入框_文本, "'))))"))
}
when 按钮_Base64解码.Click() {
Web浏览器1.RunJavaScript(join("window.AppInventor.setWebViewString(decodeURIComponent(escape(atob('", 输入框_文本, "'))))"))
}
while Web浏览器1.WebViewStringChange(值) {
标签_结果.Text = 值
}
方案四:SHA-256哈希(推荐用于密码存储)
SHA-256是单向哈希,不可逆,适合密码存储验证。
HTML文件(crypto.html)
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"></head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js"></script>
<script>
setInterval(function() {
var data = window.AppInventor.getWebViewString();
if (data && data !== "") {
try {
var parts = data.split("|||");
if (parts[0] === "sha256") {
window.AppInventor.setWebViewString("SHA:" + CryptoJS.SHA256(parts[1]).toString());
} else if (parts[0] === "aes_encrypt") {
var encrypted = CryptoJS.AES.encrypt(parts[1], parts[2]).toString();
window.AppInventor.setWebViewString("ENC:" + encrypted);
} else if (parts[0] === "aes_decrypt") {
var decrypted = CryptoJS.AES.decrypt(parts[1], parts[2]).toString(CryptoJS.enc.Utf8);
window.AppInventor.setWebViewString("DEC:" + decrypted);
} else if (parts[0] === "hmac") {
var hmac = CryptoJS.HmacSHA256(parts[1], parts[2]).toString();
window.AppInventor.setWebViewString("HMAC:" + hmac);
}
} catch(e) {
window.AppInventor.setWebViewString("ERROR:" + e.message);
}
}
}, 100);
</script>
</body>
</html>
App Inventor使用
when Screen1.Initialize() {
Web浏览器1.HomeUrl = "file:///android_asset/crypto.html"
// SHA-256哈希
}
when 按钮_哈希.Click() {
Web浏览器1.WebViewString = join("sha256|||", 文本输入框_原文.Text)
// AES加密
}
when 按钮_AES加密.Click() {
Web浏览器1.WebViewString = join("aes_encrypt|||", 文本输入框_原文.Text, "|||", 文本输入框_密钥.Text)
// AES解密
}
when 按钮_AES解密.Click() {
Web浏览器1.WebViewString = join("aes_decrypt|||", 文本输入框_密文.Text, "|||", 文本输入框_密钥.Text)
}
while Web浏览器1.WebViewStringChange(值) {
if startsAt(值, "SHA:") == 1 {
标签_哈希结果.Text = replaceall(值, "SHA:", "")
} else if startsAt(值, "ENC:") == 1 {
标签_加密结果.Text = replaceall(值, "ENC:", "")
} else if startsAt(值, "DEC:") == 1 {
标签_解密结果.Text = replaceall(值, "DEC:", "")
}
}
实战案例:加密记事本
功能需求
- 用户输入笔记内容
- 使用AES加密后保存到TinyDB
- 读取时解密显示
- 密码验证使用SHA-256
积木块代码
global 用户密码哈希 = ""
when Screen1.Initialize() {
Web浏览器1.HomeUrl = "file:///android_asset/crypto.html"
// 检查是否已设置密码
var 保存的哈希 = 微数据库1.GetValue("password_hash", "")
if 保存的哈希 == "" {
标签_状态.Text = "首次使用,请设置密码"
} else {
标签_状态.Text = "请输入密码登录"
// 设置密码
}
}
when 按钮_设置密码.Click() {
Web浏览器1.WebViewString = join("sha256|||", 文本输入框_密码.Text)
// 保存加密笔记
}
when 按钮_保存.Click() {
Web浏览器1.WebViewString = join("aes_encrypt|||", 文本输入框_笔记.Text, "|||", 文本输入框_密码.Text)
// 读取加密笔记
}
when 按钮_读取.Click() {
var 加密笔记 = 微数据库1.GetValue("encrypted_note", "")
if 加密笔记 != "" {
Web浏览器1.WebViewString = join("aes_decrypt|||", 加密笔记, "|||", 文本输入框_密码.Text)
}
}
while Web浏览器1.WebViewStringChange(值) {
if startsAt(值, "SHA:") == 1 {
var 用户密码哈希 = replaceall(值, "SHA:", "")
微数据库1.StoreValue("password_hash", 用户密码哈希)
标签_状态.Text = "✅ 密码已设置"
} else if startsAt(值, "ENC:") == 1 {
var 加密数据 = replaceall(值, "ENC:", "")
微数据库1.StoreValue("encrypted_note", 加密数据)
标签_状态.Text = "✅ 笔记已加密保存"
} else if startsAt(值, "DEC:") == 1 {
var 解密笔记 = replaceall(值, "DEC:", "")
文本输入框_笔记.Text = 解密笔记
标签_状态.Text = "✅ 笔记已解密"
} else if startsAt(值, "ERROR:") == 1 {
标签_状态.Text = "❌ 解密失败,密码错误?"
}
}
加密方案对比
| 方案 | 可逆 | 安全性 | 用途 |
|---|---|---|---|
| Caesar | ✅ | ⭐ | 教学、简单隐藏 |
| XOR | ✅ | ⭐⭐ | 简单加密、学习 |
| Base64 | ✅ | ⭐ | 编码转换,非加密 |
| SHA-256 | ❌ | ⭐⭐⭐ | 密码哈希、数据校验 |
| AES | ✅ | ⭐⭐⭐⭐⭐ | 数据加密、通信加密 |
常见问题
Q1: 加密后的中文显示乱码?
确保使用UTF-8编码处理。WebView方案中CryptoJS默认支持UTF-8。积木块方案需要处理多字节字符(中文字符占3个字节)。
Q2: WebView加载CryptoJS需要网络?
CDN方式需要网络。可以将crypto-js.min.js下载后放到Assets中,使用本地引用:
<script src="file:///android_asset/crypto-js.min.js"></script>
Q3: AES加密的密钥有多长?
CryptoJS支持128/192/256位密钥。传入的密钥字符串会被自动处理。建议使用至少16字符的密钥。
总结
- 密码存储 → SHA-256哈希
- 数据加密 → AES(WebView + CryptoJS)
- 简单隐藏 → Caesar或XOR
- 编码转换 → Base64
扫码添加客服咨询