【问题标题】:How to store RSA Private Key on android app如何在 Android 应用程序上存储 RSA 私钥
【发布时间】:2015-07-23 14:22:45
【问题描述】:

我确实看过这篇文章:Cannot generate RSA private Key on Android,但它对我不起作用。

我的想法是使用 RSA 加密来加密访问令牌并将私钥存储在设备上。我已经使用 RSA 成功加密了令牌,但我不知道存储此密钥的最佳位置在哪里。我尝试使用 KeyStore 存储它,但是我对此知之甚少,无法调试它为什么不起作用。不断收到错误:java.security.UnrecoverableKeyException:不匹配。

我的钥匙确实匹配,但同样,我不知道出了什么问题,因为我对此知之甚少。我正在使用 setEntry 并以奇怪而奇妙的方式存储私钥,我敢肯定,如果它有效,则在返回时不会是相同的密钥。

存储此私钥的最佳方式是什么?在哪里???

我不是安全专家,因此如果我更愿意使用 AES,我们将不胜感激任何建议?

我的代码如下,我只使用了 1 个活动。

package com.example.rsatest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStore.LoadStoreParameter;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.ProtectionParameter;
import java.security.KeyStore.SecretKeyEntry;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.DropBoxManager.Entry;
import android.util.Base64;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;


public class MainActivity extends Activity {
String keyStoreFile;
Key privateKey = null;
boolean isUnlocked = false;
KeyStore keyStore = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    keyStoreFile = this.getFilesDir() + "/bpstore.keystore";
    try {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            startActivity(new Intent("android.credentials.UNLOCK"));
            isUnlocked = true;
        } else {
            startActivity(new Intent("com.android.credentials.UNLOCK"));
            isUnlocked = true;
        }
    } catch (ActivityNotFoundException e) {
        Log.e("TAG", "No UNLOCK activity: " + e.getMessage(), e);
        isUnlocked = false;
    }

    if(isUnlocked){
        privateKey = GetPrivateKey();

        try{
            char[] pw =("123").toCharArray();
            keyStore = createKeyStore(this,keyStoreFile, pw);
            PasswordProtection keyPassword = new PasswordProtection("pw-secret".toCharArray());

            SecretKey sk = new SecretKey() {

                @Override
                public String getFormat() {
                    // TODO Auto-generated method stub
                    return privateKey.getFormat();
                }

                @Override
                public byte[] getEncoded() {
                    // TODO Auto-generated method stub
                    return privateKey.getEncoded();
                }

                @Override
                public String getAlgorithm() {
                    // TODO Auto-generated method stub
                    return privateKey.getAlgorithm();
                }
            };
            System.out.println(sk.getEncoded());
            System.out.println(privateKey.getEncoded());
            KeyStore.SecretKeyEntry ent = new SecretKeyEntry(sk);
            keyStore.setEntry("pk", ent, keyPassword);
            keyStore.store(new FileOutputStream(keyStoreFile), pw);

            KeyStore keyStore2;
            keyStore2 = KeyStore.getInstance("BKS");
            keyStore2.load(new FileInputStream(keyStoreFile), pw);
            KeyStore.Entry entry = keyStore2.getEntry("pk", keyPassword);
            KeyStore.SecretKeyEntry entOut = (KeyStore.SecretKeyEntry)entry;
        }catch(Exception ex){
            System.out.println("Error: " + ex.toString());
        }

    }

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

private KeyStore createKeyStore(Context context, String fileName, char[] pw) throws Exception {
    System.out.println("[DIR]:" + fileName);
    File file = new File(fileName);

    keyStore = KeyStore.getInstance("BKS");

    if (file.exists()) 
    {
        keyStore.load(new FileInputStream(file), pw);
    } else 
    {
        keyStore.load(null, null);
        keyStore.store(new FileOutputStream(fileName), pw);
    }

    return keyStore;
}

private Key GetPrivateKey(){
    String theTestText = "This is just a simple test!";

    Key publicKey = null;

    Key privateKey = null;
    try {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.genKeyPair();
        publicKey = kp.getPublic();
        privateKey = kp.getPrivate();
    } catch (Exception e) {
        Log.e("", "RSA key pair error");
    }

    // Encode the original data with RSA private key
    byte[] encodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("RSA");
        c.init(Cipher.ENCRYPT_MODE, privateKey);
        encodedBytes = c.doFinal(theTestText.getBytes());
    } catch (Exception e) {
        Log.e("", "RSA encryption error");
    }

    // Decode the encoded data with RSA public key
    byte[] decodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("RSA");
        c.init(Cipher.DECRYPT_MODE, publicKey);
        decodedBytes = c.doFinal(encodedBytes);
    } catch (Exception e) {
        Log.e("", "RSA decryption error");
    }
    return privateKey;
}
}

提前致谢, 沃伦

【问题讨论】:

  • 其他帖子是一个非常具体的错误。它没有正确的标签,所以每个人都错过了它。关于您的代码;您为什么要尝试将非对称密钥存储为对称密钥 (SecretKey)?那肯定行不通。请注意,Java 密钥库接口几乎旨在存储密钥 + 证书。您可能只想对 RSA 私钥使用另一种存储方法(例如,使用 Cipher 自己包装它们)。
  • 谢谢 Maarten,非常感谢。我会看看用密码包装它,看看我能想出什么。

标签: java android encryption cryptography keystore


【解决方案1】:

我们最终没有尝试将 RSA 私钥添加到密钥库,而是使用 AES 并使用密码对其进行包装。我们还为我们的 Android 项目添加了 ProGuard,以使我们的 APK 更难反编译。

感谢 Maarten Bodewes 的回答和帮助。

其他帖子是一个非常具体的错误。它没有正确的标签,所以每个人都错过了它。关于您的代码;为什么要尝试将非对称密钥存储为对称密钥(SecretKey)?那肯定行不通。请注意,Java 密钥库接口几乎旨在存储密钥 + 证书。您可能只想对 RSA 私钥使用另一种存储方法(例如,使用 Cipher 自己包装它们)。

【讨论】:

    猜你喜欢
    • 2013-12-04
    • 2017-12-23
    • 2010-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多