当前位置: 首页 > news >正文

安卓逆向(签名校验)

签名校验就是用来检查一个请求或数据包是否被篡改,是否在传输过程中被更改过。

工作原理:

  1. 创建签名:

    • 客户端或发送方通过某种加密算法(例如 HMAC)计算消息的“签名”。
    • 计算签名时,客户端会使用私有的密钥和消息本身的内容一起计算,生成一段加密字符串(签名)。

    这个签名是基于消息内容和密钥生成的,意味着如果消息内容发生了任何变化,签名也会变化。

String message = "City=Shanghai&Temperature=30";
String secretKey = "mySecretKey";
String signature = HMAC.calculateHMAC(message, secretKey);  // 计算签名

发送签名:

  • 客户端将生成的签名和数据一起发送给服务器。
  • 例如,客户端可能会发送一个包含数据和签名的请求:
Data: City=Shanghai&Temperature=30
Signature: d13b2e4f5c29a8de75a3b1b68eaf7e57c7b4f9f95cc27b228c7d9fa38d0d4978

校验签名:

  • 服务器收到请求后,会使用与客户端相同的算法和密钥(如果是对称加密的话)重新计算消息的签名。
  • 然后,服务器将重新计算的签名与客户端发送的签名进行对比。

如果两者相同,说明消息在传输过程中没有被篡改,且是客户端发送的合法请求;如果不同,说明消息的内容可能被篡改过。

String calculatedSignature = HMAC.calculateHMAC("City=Shanghai&Temperature=30", "mySecretKey");
if (!calculatedSignature.equals(receivedSignature)) {
    throw new SecurityException("Signature validation failed! Data might be tampered.");
}

签名的作用:

  1. 防止篡改: 如果数据在传输过程中被修改,签名就会不匹配,从而发现数据被篡改。
  2. 身份验证: 如果签名匹配,服务器可以确信数据是由客户端发送的,并且数据没有被篡改。
  3. 确保数据完整性: 签名能保证接收到的数据和发送的数据是一模一样的。

如果攻击者获得了客户端的密钥,并知道签名所用的加密算法和参数,那么他们就有可能伪造有效的请求。签名的安全性依赖于密钥的保密性,因此保护好密钥是防止伪造请求的关键。

1. 加密存储密钥

使用 Android Keystore 存储密钥

Android 提供了 Keystore 系统,它允许你存储加密密钥并对其进行加密操作,而不直接暴露密钥本身。使用 Keystore 可以确保密钥不会被泄露,因为密钥是存储在安全硬件中。

import android.security.keystore.KeyGenParameterSpec;  // 导入密钥生成参数规范类,用于指定密钥的属性和使用方式
import android.security.keystore.KeyProperties;  // 导入密钥属性类,用于定义加密算法和密钥用途
import android.util.Base64;  // 导入 Base64 编解码工具类

import javax.crypto.Cipher;  // 导入用于加解密操作的类
import javax.crypto.KeyGenerator;  // 导入密钥生成器类,用于生成对称加密密钥
import javax.crypto.SecretKey;  // 导入对称密钥类,代表加密和解密所用的密钥
import java.security.KeyStore;  // 导入密钥库类,用于存储密钥
import java.security.NoSuchAlgorithmException;  // 导入异常类,用于处理没有对应加密算法的错误
import java.security.cert.CertificateException;  // 导入证书异常类,用于处理证书相关错误

public class KeyStoreExample {

    private static final String KEY_ALIAS = "MyAppKeyAlias";  // 定义密钥的别名,用于在 KeyStore 中查找该密钥
    private KeyStore keyStore;  // 声明 KeyStore 实例变量,用于访问 Android KeyStore

    // 构造方法,初始化 KeyStore 实例
    public KeyStoreExample() throws Exception {
        keyStore = KeyStore.getInstance("AndroidKeyStore");  // 获取 AndroidKeyStore 实例
        keyStore.load(null);  // 加载 KeyStore(null 表示加载默认配置)
    }

    // 创建密钥并保存到 Keystore 中
    public void createKey() throws Exception {
        // 创建 KeyGenerator 实例,用于生成密钥
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

        // 初始化 KeyGenerator,并指定密钥用途和加密方式
        keyGenerator.init(
                new KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)  // 设置密钥别名和用途(加密、解密)
                        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)  // 设置块模式为 GCM(Galois/Counter Mode),用于加密
                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)  // 设置加密填充方式为无填充
                        .build()  // 创建密钥生成参数配置对象
        );

        keyGenerator.generateKey();  // 根据配置生成密钥并存储在 KeyStore 中
    }

    // 使用 Keystore 中的密钥进行加密操作
    public String encryptData(String inputData) throws Exception {
        // 从 KeyStore 中获取存储的密钥
        SecretKey key = (SecretKey) keyStore.getKey(KEY_ALIAS, null);

        // 创建 Cipher 实例,用于执行加密操作
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");  // 使用 AES 加密算法,块模式为 GCM,且无填充
        cipher.init(Cipher.ENCRYPT_MODE, key);  // 初始化 Cipher 为加密模式,并使用 Keystore 中的密钥

        // 获取初始化向量(IV),它是 GCM 模式中必需的
        byte[] iv = cipher.getIV();
        // 执行加密操作,输入数据被加密为字节数组
        byte[] encryption = cipher.doFinal(inputData.getBytes());  // 将输入数据转换为字节数组并进行加密

        // 将加密后的数据和 IV 合并,并用 Base64 编码方便传输
        return Base64.encodeToString(encryption, Base64.DEFAULT) + ":" + Base64.encodeToString(iv, Base64.DEFAULT);
    }

    // 使用 Keystore 中的密钥进行解密操作
    public String decryptData(String encryptedData) throws Exception {
        // 将加密后的数据和 IV 从传输字符串中分离
        String[] parts = encryptedData.split(":");  // 分割加密数据和 IV
        byte[] encryption = Base64.decode(parts[0], Base64.DEFAULT);  // 对加密数据进行 Base64 解码
        byte[] iv = Base64.decode(parts[1], Base64.DEFAULT);  // 对 IV 进行 Base64 解码

        // 从 KeyStore 中获取存储的密钥
        SecretKey key = (SecretKey) keyStore.getKey(KEY_ALIAS, null);

        // 创建 Cipher 实例,用于执行解密操作
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");  // 使用 AES 加密算法,块模式为 GCM,且无填充
        // 初始化 Cipher 为解密模式,并使用获取的 IV
        cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));  // 使用 IV 创建 GCMParameterSpec 以便解密

        // 执行解密操作,恢复原始数据
        byte[] original = cipher.doFinal(encryption);  // 解密数据

        // 将解密后的字节数组转换为字符串并返回
        return new String(original);  // 将字节数组转换为字符串并返回
    }
}

代码解释:
  • KeyStore 是用于存储和管理密钥的 Android 系统组件。
  • KeyGenParameterSpec.Builder 用来创建密钥生成的配置,确保密钥只能用于加密和解密操作。
  • Cipher 用来执行加密和解密。加密后数据和 IV 会一起存储,解密时需要使用同样的 IV。

Cipher 是 Java 和 Android 中用于加密和解密数据的类。它是 javax.crypto.Cipher 类的一部分,提供了一种方法来执行加密和解密操作,支持多种加密算法和模式。

Cipher 类的作用:

  1. 加密:使用对称加密算法(例如 AES、DES 等)将明文数据转化为加密后的密文。
  2. 解密:使用相同的算法和密钥将加密后的密文还原为明文数据。

GCM(Galois/Counter Mode)是一种加密模式,它结合了加密和认证功能,用于确保数据的机密性完整性。GCM 是基于计数器模式(CTR)的,并使用一个额外的认证标签来验证数据是否在传输过程中被篡改。

主要特点:

  1. 加密性(Confidentiality):像其他加密模式一样,GCM 用于加密数据,确保只有授权的接收者能够读取数据内容。
  2. 完整性(Integrity):GCM 还提供认证功能,确保加密的数据在传输过程中没有被篡改。认证标签用于验证数据的完整性。

工作原理:

GCM 模式结合了加密和认证的功能,具体步骤如下:

  1. 加密:使用计数器模式(CTR)对数据进行加密。CTR 模式每次使用一个不同的计数器值(IV + nonce)来生成密钥流,将明文与密钥流进行异或操作,得到密文。
  2. 认证:同时计算认证标签(Authentication Tag),这个标签是通过对加密数据和一些附加数据(如头信息等)进行特定的数学操作(Galois 域上的乘法)来生成的,确保数据在传输过程中没有被篡改。

2. 密钥管理

密钥的定期更换

定期更换密钥是防止密钥长期泄露的有效措施。密钥的更换可以通过引入新的密钥别名来完成。

示例代码:

public void rotateKey() throws Exception {
    // 删除旧密钥(如果有的话)
    if (keyStore.containsAlias(KEY_ALIAS)) {
        keyStore.deleteEntry(KEY_ALIAS);  // 删除旧密钥
    }

    // 创建新密钥
    createKey();
}

通过 rotateKey() 方法,我们可以删除旧的密钥,并创建一个新的密钥。定期更换密钥可以降低密钥泄露后的风险。

3. 密钥保护的传输

使用 HTTPS 保护传输

在客户端和服务器之间传输密钥或密钥加密的数据时,使用 HTTPS 来加密整个通信通道,以防止密钥和其他敏感数据在传输过程中被中间人窃取。

// 使用 OkHttp 发起 HTTPS 请求
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
        .url("https://secure.example.com/endpoint")
        .addHeader("Authorization", "Bearer your-token")
        .build();

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        // 处理响应
    }

    @Override
    public void onFailure(Call call, IOException e) {
        // 处理失败
    }
});

在客户端,OkHttp 默认会使用 HTTPS 协议来加密数据传输,确保中间人无法篡改或窃取传输的数据。

4. 结合时间戳和随机数

为进一步增加安全性,可以在每个请求中加入时间戳和随机数(nonce)来防止重放攻击。每个请求都必须包含唯一的时间戳和随机数,以确保每个请求都是唯一的。

public String generateRequestSignature(String data, long timestamp, String nonce) {
    String input = data + timestamp + nonce;
    return calculateSignature(input);
}

private String calculateSignature(String input) {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
        return Base64.encodeToString(hash, Base64.DEFAULT);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return "";
    }
}
代码解释:
  • 使用时间戳和随机数作为加密数据的一部分。
  • 使用 SHA-256 算法生成签名,确保请求的完整性和唯一性。

总结:

密钥保护的关键是存储安全、管理安全和传输安全:

  1. 加密存储密钥:使用 Android Keystore、硬件安全模块(HSM)等保护密钥。
  2. 密钥管理:定期轮换密钥,并确保每个密钥的生命周期受到有效管理。
  3. 加密传输:使用 HTTPS 协议确保密钥和加密数据在网络传输中不被泄露。
  4. 防止重放攻击:结合时间戳和随机数(nonce)等技术,防止攻击者伪造请求。

密钥保护

使用 HTTPS

使用短期有效的令牌(Token)

签名结合时间戳

Nonce(随机数)机制

双向认证(Mutual Authentication)

相关文章:

  • SQL 注入漏洞原理以及修复方法
  • 开源语音克隆项目 OpenVoice V2 本地部署
  • 数据治理常用的开源项目有哪些?
  • CAS单点登录(第7版)2.规划
  • 数据结构与算法之排序算法-(计数,桶,基数排序)
  • 阿里云上线 DeepSeek,AI 领域再掀波澜
  • UE C++ UObject 功能的初步总结
  • 工作室如何实现一机一IP
  • moveable 一个可实现前端海报编辑器的 js 库
  • 进阶关卡 - 第4关 - InternVL 多模态模型部署微调实践
  • 第二月:学习 NumPy、Pandas 和 Matplotlib 是数据分析和科学计算的基础
  • CAS单点登录(第7版)7.授权
  • flv实时监控视频
  • Linux网络 | 多路转接selec
  • 基于web的留守儿童网站的设计与实现
  • 【C/C++】C++ Vector容器核心操作指南:增删改查全面解析
  • Kubernetes:容器编排的革命与未来
  • 领域模型:驱动软件进化的战略核心与实践指南
  • 如何让内网下其他主机直接通过 ip 访问docker overlay 网段下对应容器?
  • 【C++内存管理】—— 策略、陷阱及应对之道
  • 被炒热的“高潮针”:超适应症使用,安全性和有效性存疑
  • 视觉周刊|劳动开创未来
  • 抗战回望16︱《青年生活》《革命青年》:抗战与青年
  • 经济日报:合力推进民企与毕业生双向奔赴
  • 观察|印度购买“阵风”舰载机,为掌控印度洋加速升级海航装备
  • 严正交涉!我驻日使馆:如日方采取新的挑衅举动,中方必坚决反制