gpt4 book ai didi

java - 如何安全地将敏感数据(短字符串)存储到 keystore 中

转载 作者:太空宇宙 更新时间:2023-11-04 12:05:47 26 4
gpt4 key购买 nike

我需要将敏感数据(小字符串)存储到 keystore 中。这里描述的例子几乎正是我需要做的。问题:我不太明白,我在该主题上完全是新手(密码、加密、RSA...)

https://medium.com/@ericfu/securely-storing-secrets-in-an-android-application-501f030ae5a3#.oqvxbjn8m

这就是我正在研究的类(class)(基于上面提到的这篇文章):

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.security.KeyPairGeneratorSpec;
import android.security.keystore.KeyProperties;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Calendar;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.x500.X500Principal;


public class SecondActivity extends AppCompatActivity {

static final String TAG = "SimpleKeystoreApp";
static final String CIPHER_PROVIDER = "AndroidOpenSSL";
private static final String RSA_MODE = "RSA/ECB/PKCS1Padding";
private static final String AES_MODE = "AES/ECB/PKCS7Padding";
private static final String KEY_ALIAS = "this is my alias";
private static final String SHARED_PREFENCE_NAME = "my shared_prefs";
private static final String ENCRYPTEDKEY_KEY = "encrypted_key";
private static final String TO_BE_ENCRYPTED_KEY = "this is my test";
private static final String ANDROID_KEYSTORE = "AndroidKeyStore";

KeyStore keyStore;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
keyStore.load(null);
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}

createNewKeys();

try {
generateAndStoreAESKey();
} catch (Exception e) {
Log.d(TAG, "couldn't generateAndStoreAESKey:" + e.getMessage());
}
String encrypted = null;
try {
encrypted = encrypt(getApplicationContext(), TO_BE_ENCRYPTED_KEY.getBytes());
Log.d(TAG, "encrypted:" + encrypted);
} catch (Exception e) {
Log.d(TAG, "couldn't encrypt:" + e.getMessage());
}

try {
decrypt(getApplicationContext(), encrypted.getBytes());
Log.d(TAG, "decrypted:" + encrypted);
} catch (Exception e) {
Log.d(TAG, "couldn't decrypt:" + e.getMessage());
}
setContentView(R.layout.activity_main);
}

public void createNewKeys() {
Log.d(TAG, "___ createNewKeys");
try {
// Create new key if needed
// Generate the RSA key pairs
keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
keyStore.load(null);
// Generate the RSA key pairs
if (!keyStore.containsAlias(KEY_ALIAS)) {
// Generate a key pair for encryption
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 30);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
.setAlias(KEY_ALIAS)
.setSubject(new X500Principal("CN=" + KEY_ALIAS))
.setSerialNumber(BigInteger.TEN)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEYSTORE);
kpg.initialize(spec);
kpg.generateKeyPair();

KeyPair keyPair = kpg.generateKeyPair();
Log.d(TAG, "Public Key is: " + keyPair.getPublic().toString());
}
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occured", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}

private void generateAndStoreAESKey() throws Exception{
Log.d(TAG, "___ generateAndStoreAESKey");

SharedPreferences pref = getApplicationContext().getSharedPreferences(SHARED_PREFENCE_NAME, Context.MODE_PRIVATE);
String enryptedKeyB64 = pref.getString(ENCRYPTEDKEY_KEY, null);
if (enryptedKeyB64 == null) {
byte[] key = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(key);
byte[] encryptedKey = rsaEncrypt(key);
enryptedKeyB64 = Base64.encodeToString(encryptedKey, Base64.DEFAULT);
SharedPreferences.Editor edit = pref.edit();
edit.putString(ENCRYPTEDKEY_KEY, enryptedKeyB64);
edit.commit();
}
}
private SecretKeySpec getSecretKey(Context context) throws Exception{
SharedPreferences pref = context.getSharedPreferences(SHARED_PREFENCE_NAME, Context.MODE_PRIVATE);
String enryptedKeyB64 = pref.getString(ENCRYPTEDKEY_KEY, null);
// need to check null, omitted here
byte[] encryptedKey = Base64.decode(enryptedKeyB64, Base64.DEFAULT);
byte[] key = rsaDecrypt(encryptedKey);
return new SecretKeySpec(key, "AES");
}

public String encrypt(Context context, byte[] input) throws Exception{
Cipher c = Cipher.getInstance(AES_MODE, "BC");
c.init(Cipher.ENCRYPT_MODE, getSecretKey(context));
byte[] encodedBytes = c.doFinal(input);
String encryptedBase64Encoded = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
return encryptedBase64Encoded;
}


public byte[] decrypt(Context context, byte[] encrypted) throws Exception{
Cipher c = Cipher.getInstance(AES_MODE, "BC");
c.init(Cipher.DECRYPT_MODE, getSecretKey(context));
byte[] decodedBytes = c.doFinal(encrypted);
return decodedBytes;
}


private byte[] rsaEncrypt(byte[] secret) throws Exception{
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
// Encrypt the text
Cipher inputCipher = Cipher.getInstance(RSA_MODE, CIPHER_PROVIDER);
inputCipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey());

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, inputCipher);
cipherOutputStream.write(secret);
cipherOutputStream.close();

byte[] vals = outputStream.toByteArray();
return vals;
}

private byte[] rsaDecrypt(byte[] encrypted) throws Exception {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
Cipher output = Cipher.getInstance(RSA_MODE, CIPHER_PROVIDER);
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(encrypted), output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}

byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
return bytes;
}
}

我有一个 InvalidKeyException:调用时需要抛出 RSA 私钥或公钥

outputCipher.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());

private  byte[]  rsaDecrypt(byte[] encrypted)

所以我需要能够解密 keystore 中存储的私钥,但此操作给我一个错误。

我不明白为什么。也许流程出了问题?请用简单的话解释我做错了什么。

最佳答案

@Robert 在评论中的回答解决了我的问题:我从

中删除了 CIPHER_PROVIDER

密码输入Cipher = Cipher.getInstance(RSA_MODE, CIPHER_PROVIDER);

关于java - 如何安全地将敏感数据(短字符串)存储到 keystore 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40384001/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com