Android-KeyStore安全的存储系统


在 Android 中,AndroidKeyStore 是一个安全的存储系统,用于存储加密密钥。它提供了一种安全的方式来生成、存储和管理密钥,而无需将密钥暴露给应用程序本身。以下是如何使用 AndroidKeyStore 的基本步骤和示例代码。

检查 AndroidKeyStore 是否可用

AndroidKeyStore 在 Android API 18(Android 4.3)及以上版本中可用。确保你的应用支持这些版本。

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
    // AndroidKeyStore 不可用
    return;
}

完整 Java 示例

import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;

import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;

public class AndroidKeyStoreExample {

    // 密钥库类型
    private static final String PP_KEYSTORE_TYPE = "AndroidKeyStore";
    // 密钥库别名
    private static final String PP_KEYSTORE_ALIAS = "pp_keystore_alias";
    // 加密算法标准名称
    private static final String PP_TRANSFORMATION = "RSA/ECB/PKCS1Padding";

    public static void main(String[] args) {
        try {
            // 创建 RSA 密钥对
            createRsaKeyPair(PP_KEYSTORE_ALIAS);

            // 获取公钥和私钥
            PublicKey publicKey = getPublicKey(PP_KEYSTORE_ALIAS);
            PrivateKey privateKey = getPrivateKey(PP_KEYSTORE_ALIAS);

            // 原始数据
            String originalText = "Hello, AndroidKeyStore!";
            System.out.println("Original Text: " + originalText);

            // 使用公钥加密数据
            byte[] encryptedData = encryptData(publicKey, originalText.getBytes(StandardCharsets.UTF_8));
            System.out.println("Encrypted Data: " + new String(encryptedData, StandardCharsets.UTF_8));

            // 使用私钥解密数据
            byte[] decryptedData = decryptData(privateKey, encryptedData);
            System.out.println("Decrypted Data: " + new String(decryptedData, StandardCharsets.UTF_8));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建 RSA 密钥对
     */
    public static void createRsaKeyPair(String alias) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
            KeyProperties.KEY_ALGORITHM_RSA, PP_KEYSTORE_TYPE
        );

        KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
            alias,
            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT
        )
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
            .build();

        keyPairGenerator.initialize(spec);
        keyPairGenerator.generateKeyPair();
    }

    /**
     * 获取公钥
     */
    public static PublicKey getPublicKey(String alias) throws Exception {
        KeyStore keyStore = KeyStore.getInstance(PP_KEYSTORE_TYPE);
        keyStore.load(null); // 加载 AndroidKeyStore

        return keyStore.getCertificate(alias).getPublicKey();
    }

    /**
     * 获取私钥
     */
    public static PrivateKey getPrivateKey(String alias) throws Exception {
        KeyStore keyStore = KeyStore.getInstance(PP_KEYSTORE_TYPE);
        keyStore.load(null); // 加载 AndroidKeyStore

        return (PrivateKey) keyStore.getKey(alias, null);
    }

    /**
     * 使用公钥加密数据
     */
    public static byte[] encryptData(PublicKey publicKey, byte[] data) throws Exception {
        Cipher cipher = Cipher.getInstance(PP_TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 使用私钥解密数据
     */
    public static byte[] decryptData(PrivateKey privateKey, byte[] encryptedData) throws Exception {
        Cipher cipher = Cipher.getInstance(PP_TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(encryptedData);
    }
}

代码说明

1. 创建 RSA 密钥对
  • 使用 KeyPairGeneratorKeyGenParameterSpec 创建一个 RSA 密钥对。
  • KeyGenParameterSpec.Builder 用于指定密钥的用途(加密和解密)、填充方式等配置。
2. 获取公钥和私钥
  • 公钥通过 KeyStore.getCertificate(alias).getPublicKey() 获取。
  • 私钥通过 KeyStore.getKey(alias, null) 获取。
3. 加密数据
  • 使用公钥和指定的加密算法(RSA/ECB/PKCS1Padding)对数据进行加密。
4. 解密数据
  • 使用私钥和相同的加密算法对加密后的数据进行解密。

运行结果

假设原始数据是 "Hello, AndroidKeyStore!",运行程序后会输出:

Original Text: Hello, AndroidKeyStore!
Encrypted Data: [加密后的二进制数据]
Decrypted Data: Hello, AndroidKeyStore!

注意事项

  1. API 版本要求

    • AndroidKeyStore 支持 API 18 及以上版本。
    • 如果需要在更低版本中实现类似功能,可以考虑使用其他加密库(如 Bouncy Castle)。
  2. 异常处理

    • 在实际开发中,务必捕获并处理可能抛出的异常,例如:
      • KeyStoreException
      • NoSuchAlgorithmException
      • InvalidKeyException
      • IllegalBlockSizeException
      • BadPaddingException
  3. 安全性

    • 使用 setUserAuthenticationRequired(true) 可以要求用户认证(如指纹或 PIN 码)才能访问密钥。
    • 避免将敏感数据存储在内存中太久,减少泄露风险。
  4. 填充方式

    • PKCS1Padding 是常用的填充方式,但如果你需要更高的安全性,可以考虑更现代的填充方式(如 OAEP)。

通过以上代码和解释,你应该能够理解如何在 Android 应用中使用 AndroidKeyStore 来安全地生成密钥、加密和解密数据。如果有进一步的问题,请随时提问!

<think>嗯,用户想在Unity里集成穿山甲广告SDK。首先,我需要回忆一下穿山甲SDK的集成步骤。根据之前的引用资料,比如引用[2]提到通过TopOn聚合平台来集成,可能需要先下载SDK,然后导入Unity。另外,引用[2]还提到要添加各平台的ID和Key,所以用户需要去穿山甲后台申请账号获取这些信息。 然后,用户可能需要知道具体的步骤,比如在Unity中导入包,配置Android和iOS的设置。比如,Android可能需要修改Gradle配置,添加依赖库,而iOS可能需要额外的步骤,比如引用[3]提到的iOS Native接入,需要处理CocoaPods或者手动添加框架。 另外,需要注意Unity的版本兼容性,不同版本的Unity可能需要不同的设置。还有,测试广告的时候要区分正式环境和测试环境,避免被封禁。可能需要指导用户如何添加测试设备,使用测试ID。 可能用户会遇到的问题包括SDK冲突、依赖问题,或者广告无法加载。这时候需要检查依赖库是否正确,网络权限是否添加,以及广告位ID是否正确。此外,聚合平台TopOn的配置步骤可能比较复杂,需要详细说明如何配置Waterfall和优先级。 还要提醒用户遵循各平台的政策,比如穿山甲的广告投放规则,避免违规。最后,建议用户参考官方文档,因为步骤可能会更新,确保信息的准确性。</think>### 分步指南:在Unity中集成穿山甲广告SDK #### 一、准备工作 1. **注册穿山甲开发者账号** 前往[穿山甲广告平台](https://www.csjplatform.com/)注册账号,创建应用和广告位,获取对应的`AppID`和`广告位ID`[^1]。 2. **选择集成方式** - **直接集成穿山甲原生SDK**:需下载Unity版本的穿山甲SDK包(如`Pangle SDK for Unity`)[^3]。 - **通过聚合平台(如TopOn)集成**:可同时管理多个广告平台,简化配置流程[^2]。 #### 二、直接集成穿山甲SDK(原生方式) 1. **导入SDK到Unity项目** 下载穿山甲Unity插件(`.unitypackage`文件),通过`Assets > Import Package > Custom Package`导入。 2. **Android平台配置** - 修改`mainTemplate.gradle`,添加穿山甲仓库和依赖: ```gradle repositories { maven { url "https://artifact.bytedance.com/repository/pangle" } } dependencies { implementation 'com.pangle.cn:ads-sdk:4.8.0.8' } ``` - 在`AndroidManifest.xml`中添加网络权限: ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` 3. **iOS平台配置** - 通过CocoaPods集成(需在`Podfile`中添加): ```ruby pod 'Ads-CN', '~> 4.8.0.8' ``` - 手动集成时需添加`BUAdSDK.framework`并配置`Other Linker Flags`为`-ObjC`[^3]。 4. **初始化SDK代码示例** ```csharp using Pangle; public class AdManager : MonoBehaviour { void Start() { PangleAd.Initialize("your_app_id", (success, message) => { if (success) Debug.Log("SDK初始化成功"); }); } } ``` #### 三、通过TopOn聚合平台集成(推荐) 1. **下载TopOn Unity SDK** 从[TopOn官网](https://www.toponad.com/)下载最新版SDK并导入Unity。 2. **配置广告平台参数** - 在TopOn后台录入穿山甲的`AppID`和`AppKey`。 - 设置广告位的`Waterfall优先级`和`底价策略`,支持多平台流量分组和A/B测试[^2]。 3. **广告加载示例(激励视频)** ```csharp using TopOn; public void LoadRewardedAd() { ATRewardedVideoAd.Instance.LoadAd("your_topon_ad_unit_id"); ATRewardedVideoAd.Instance.OnAdLoaded += (unitId) => { ATRewardedVideoAd.Instance.ShowAd("your_topon_ad_unit_id"); }; } ``` #### 四、测试与上线 1. **使用测试广告位ID** 穿山甲提供专用测试ID(如Android激励视频:`901121375`),避免触发正式环境校验。 2. **真机调试要点** - Android需关闭`Optimize APK Size`防止资源裁剪 - iOS需在`Info.plist`添加`SKAdNetworkItems`适配ATT框架 3. **常见问题排查** | 错误码 | 原因 | 解决方案 | |---|---|---| | 40001 | 包名不符 | 检查穿山甲后台注册包名 | | 50002 | 签名异常 | 核对签名MD5与后台是否一致 | | 20002 | 网络超时 | 检查设备网络代理设置 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不穿铠甲的穿山甲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值