【问题标题】:How to encrypt the Key and IV which used in AES Encryption Model in android App如何加密 android App 中 AES 加密模型中使用的密钥和 IV
【发布时间】:2019-07-25 12:53:16
【问题描述】:

我有一个 android 应用程序,它有支付网关和另一个服务。我使用 AES 模型来加密和解密应用程序和服务器之间的数据。我使用存储在 android 类中的 KEY 和 IV 常量。我的问题是如何在 android 应用程序中加密这些常量(IV 和 Key),以防止任何攻击者对 APK 文件进行反编译并显示这些常量。

【问题讨论】:

    标签: android .net encryption aes


    【解决方案1】:

    您必须使用 RSA 公钥加密密钥,并且只有服务器知道此公钥的私钥并可以对其进行解密。

    您使用服务器端的私钥解密 AES 密钥,并使用解密后的 AES 密钥解密您的原始消息。

    //编辑

    这是 Android Studio 中的 Java 代码示例。我的 RSA 公钥存储在共享首选项中。

    安装应用程序后,它会调用服务器,在服务器上生成 RSA 密钥对,两个密钥都保存在数据库中,公钥发送到设备并保存在共享首选项中。每当需要加密时,都会创建存储的公钥并用于加密,只有服务器知道私钥。

    byte[] ENCRYPTED_AES_KEY_IN_BYTE = null;
    String ENCRYPTED_AES_KEY;
    cipher = null;
    cipher = Cipher.getInstance("RSA/NONE/OAEPwithSHA-1andMGF1Padding");
    
    // Get the shared preferences where the public key is stored
    // SharedPreferences preferences = getApplicationContext().getSharedPreferences(preferences,Context.MODE_PRIVATE);
    
    // get the Publickey stored as string in the shared preferences
    String stringkey = preferences.getString(PUBLICKEY,"");
    
    // create a public RSA Key from the stored key
    X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decode(stringkey,Base64.DEFAULT));
    KeyFactory keyFactory;
    PublicKey key =null;
    keyFactory = KeyFactory.getInstance("RSA");
    key = keyFactory.generatePublic(spec);
    
    //Encrypt the AES key with the RSA public key
    cipher.init(Cipher.ENCRYPT_MODE, key);
    ENCRYPTED_AES_KEY_IN_BYTES = AES_KEY.getEncoded();
    
    ENCRYPTED_AES_KEY_IN_BYTE = cipher.doFinal(ENCRYPTED_AES_KEY_IN_BYTE);
    ENCRYPTED_AES_KEY = Base64.encodeToString(ENCRYPTED_AES_KEY_IN_BYTE,Base64.DEFAULT);
    
    //ENCRYPTED_AES_KEY is now the Encrypted AES Key as string
    

    // 编辑#2

    在服务器上创建一个 RSA KEY 对

    $rsa = new Crypt_RSA();
    $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS8);
    $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8);
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
    extract($rsa->createKey());
    $publickey = str_replace("-----BEGIN PUBLIC KEY-----\r\n","",$publickey);
    $publickey = str_replace("-----END PUBLIC KEY-----","",$publickey);
    $privatekey = str_replace("-----BEGIN PRIVATE KEY-----\r\n","",$privatekey);
    $privatekey = str_replace( "-----END PRIVATE KEY-----","",$privatekey);
    

    私钥保存到数据库,公钥发送给客户端加密数据。

    再次解密服务器端的数据

    $rsa = new Crypt_RSA();
    $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS8);
    $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8);
    $rsa->setEncryptionMode( CRYPT_RSA_ENCRYPTION_OAEP);
    $IV     = base64_decode($IV);
    $AESkey    = base64_decode($AESkey);
    $rsa->loadKey($privatekey);
    $AESkey    = $rsa->decrypt($AESkey);
    
    // replace empty spaces with a + , this is something which can happen when you use a http request
    
    $encrypteddata = str_replace(" ", "+", $encrypteddata);
    $encrypteddata   = base64_decode($encrypteddata);
    $method = "AES-256-CBC";
    $decrypteddata   = openssl_decrypt($encrypteddata, $method, $AESkey, OPENSSL_RAW_DATA,$IV);
    

    在此代码中不包括如何将私钥存储在数据库中以及如何从数据库中取回它。

    【讨论】:

    • 感谢您的评论,但您是否有任何示例代码在 java 作为移动端和 .net 作为服务器端使用上述方法
    • 编辑了一种加密 AES 密钥的方法,该密钥可以作为字符串发送到服务器,但我没有 .net 解决方案,只有一个 php 脚本。
    • 没问题,请您添加使用 java 和 php 的示例代码。这个想法是为了保护和隐藏密钥和 IV 免受攻击者的攻击,因为当您反编译任何 Android 应用程序时,您可以获得易于获取 IV 和密钥的源代码,然后任何人都可以解密来自服务器的数据。
    • 您的方法似乎不太安全,您永远不应该在客户端存储静态 AES 密钥。特别是对于付款,这是一个非常糟糕的主意。对于这样的方法,您在一侧进行加密,在另一侧进行解密 RSA。
    • 添加了一个php代码来生成一个RSA密钥对并用它来解密一个AES密钥,并使用解密后的AES密钥来解密原始数据
    猜你喜欢
    • 1970-01-01
    • 2012-02-21
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    • 2012-11-14
    • 2017-04-16
    • 1970-01-01
    相关资源
    最近更新 更多