App Inventor 2 文本加密教程 - 数据安全与加密方案

« 返回首页

概述

App Inventor 2没有内置加密组件,但可以通过以下方式实现文本加密:

方案 安全级别 实现方式
Caesar密码(字符偏移) 积木块直接实现
XOR异或加密 ⭐⭐ 积木块实现
Base64编码 ⭐(非加密) WebView/积木块
SHA-256哈希 ⭐⭐⭐(不可逆) WebView
AES加密 ⭐⭐⭐⭐⭐ WebView + CryptoJS

方案一:Caesar密码(凯撒密码)

最简单的加密方式,将每个字符偏移固定位数。

加密

定义 Caesar加密(原文, 偏移量) 返回 密文
  设 密文 = ""
  设 i = 1
  当 i ≤ 文本长度(原文)
    设 字符 = 文本第i个字符(原文)
    设 ASCII码 = 文本转ASCII码(字符)
    设 加密码 = ASCII码 + 偏移量
    如果 加密码 > 126
      设 加密码 = 加密码 - 94  ' 可打印ASCII范围
    设 密文 = 密文 & ASCII码转文本(加密码)
    设 i = i + 1
  返回 密文

解密

定义 Caesar解密(密文, 偏移量) 返回 原文
  返回 Caesar加密(密文, 0 - 偏移量)  ' 反向偏移

使用示例

当 按钮_加密.被点击
  设 偏移量 = 文本转数字(输入框_偏移量.文本)
  设 加密结果 = Caesar加密(输入框_原文.文本, 偏移量)
  标签_密文.文本 = 加密结果

当 按钮_解密.被点击
  设 偏移量 = 文本转数字(输入框_偏移量.文本)
  设 解密结果 = Caesar解密(输入框_密文.文本, 偏移量)
  标签_原文.文本 = 解密结果

方案二:XOR异或加密

比Caesar更安全,使用密钥进行异或运算。

定义 XOR加密(原文, 密钥) 返回 密文
  设 密文 = ""
  设 密钥长度 = 文本长度(密钥)
  设 i = 1
  当 i ≤ 文本长度(原文)
    设 原字符 = 文本转ASCII码(文本第i个字符(原文))
    设 密钥字符 = 文本转ASCII码(文本第((i-1)模密钥长度+1)个字符(密钥))
    设 异或结果 = 原字符 XOR 密钥字符  ' 使用位运算积木块
    设 密文 = 密文 & 文本转十六进制(异或结果) & " "
    设 i = i + 1
  返回 密文

定义 XOR解密(密文, 密钥) 返回 原文
  设 原文 = ""
  设 十六进制列表 = 分割文本(密文, " ")
  设 密钥长度 = 文本长度(密钥)
  设 i = 1
  当 i ≤ 列表长度(十六进制列表)
    设 加密字节 = 十六进制转数字(列表第i项(十六进制列表))
    设 密钥字符 = 文本转ASCII码(文本第((i-1)模密钥长度+1)个字符(密钥))
    设 解密字节 = 加密字节 XOR 密钥字符
    设 原文 = 原文 & ASCII码转文本(解密字节)
    设 i = i + 1
  返回 原文

注意:XOR加密的特性是 加密(加密(原文, 密钥), 密钥) = 原文,即加密和解密用同一个函数。

方案三:Base64编码

Base64不是加密,只是编码转换,但可以隐藏明文内容。

使用WebView

当 按钮_Base64编码.被点击
  调用 WebView1.运行JavaScript(
    "window.AppInventor.setWebViewString(btoa(unescape(encodeURIComponent('" & 输入框_文本.文本 & "'))))")

当 按钮_Base64解码.被点击
  调用 WebView1.运行JavaScript(
    "window.AppInventor.setWebViewString(decodeURIComponent(escape(atob('" & 输入框_文本.文本 & "'))))")

当 WebView1.WebView字符串改变(值)
  标签_结果.文本 = 值

方案四: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使用

当 Screen1.初始化
  设 WebView1.主页地址 = "file:///android_asset/crypto.html"

' SHA-256哈希
当 按钮_哈希.被点击
  设 WebView1.WebView字符串 = "sha256|||" & 输入框_原文.文本

' AES加密
当 按钮_AES加密.被点击
  设 WebView1.WebView字符串 = "aes_encrypt|||" & 输入框_原文.文本 & "|||" & 输入框_密钥.文本

' AES解密
当 按钮_AES解密.被点击
  设 WebView1.WebView字符串 = "aes_decrypt|||" & 输入框_密文.文本 & "|||" & 输入框_密钥.文本

当 WebView1.WebView字符串改变(值)
  如果 值 以 "SHA:" 开头
    标签_哈希结果.文本 = 替换文本(值, "SHA:", "")
  否则 如果 值 以 "ENC:" 开头
    标签_加密结果.文本 = 替换文本(值, "ENC:", "")
  否则 如果 值 以 "DEC:" 开头
    标签_解密结果.文本 = 替换文本(值, "DEC:", "")

实战案例:加密记事本

功能需求

  • 用户输入笔记内容
  • 使用AES加密后保存到TinyDB
  • 读取时解密显示
  • 密码验证使用SHA-256

积木块代码

设 用户密码哈希 = ""

当 Screen1.初始化
  设 WebView1.主页地址 = "file:///android_asset/crypto.html"
  ' 检查是否已设置密码
  设 保存的哈希 = TinyDB1.获取值("password_hash", "")
  如果 保存的哈希 = ""
    标签_状态.文本 = "首次使用,请设置密码"
  否则
    标签_状态.文本 = "请输入密码登录"

' 设置密码
当 按钮_设置密码.被点击
  设 WebView1.WebView字符串 = "sha256|||" & 输入框_密码.文本

' 保存加密笔记
当 按钮_保存.被点击
  设 WebView1.WebView字符串 = "aes_encrypt|||" & 输入框_笔记.文本 & "|||" & 输入框_密码.文本

' 读取加密笔记
当 按钮_读取.被点击
  设 加密笔记 = TinyDB1.获取值("encrypted_note", "")
  如果 加密笔记 ≠ ""
    设 WebView1.WebView字符串 = "aes_decrypt|||" & 加密笔记 & "|||" & 输入框_密码.文本

当 WebView1.WebView字符串改变(值)
  如果 值 以 "SHA:" 开头
    设 用户密码哈希 = 替换文本(值, "SHA:", "")
    调用 TinyDB1.存储值("password_hash", 用户密码哈希)
    标签_状态.文本 = "✅ 密码已设置"
  否则 如果 值 以 "ENC:" 开头
    设 加密数据 = 替换文本(值, "ENC:", "")
    调用 TinyDB1.存储值("encrypted_note", 加密数据)
    标签_状态.文本 = "✅ 笔记已加密保存"
  否则 如果 值 以 "DEC:" 开头
    设 解密笔记 = 替换文本(值, "DEC:", "")
    输入框_笔记.文本 = 解密笔记
    标签_状态.文本 = "✅ 笔记已解密"
  否则 如果 值 以 "ERROR:" 开头
    标签_状态.文本 = "❌ 解密失败,密码错误?"

加密方案对比

方案 可逆 安全性 用途
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

版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。

文档反馈