需要在应用程序上实现端到端加密。发送和接收的所有数据都将被加密。使用我从服务器获取的公共密钥加密后,需要将在应用程序上生成并存储在Android Keystore中的对称秘密密钥发送到服务器。问题:我无法获取要加密的SecretKey的字符串/字节值。
我有一个帮助程序类,该类负责生成SecretKey并在需要时从密钥库中存储和检索它。数据已正确加密和解密,但是由于需要端加密(传输中的所有数据也必须加密),我需要将密钥发送到服务器,但无法访问它。 SecretKey类中有三种getter方法。 getAlgortithm-这将按预期返回“ AES” getEncoded-返回null getFormat-这还将返回null
public class EncryptionKeyGenerator {
public static final String ANDROID_KEY_STORE = "AndroidKeyStore";
public static final String KEY_ALIAS = "KEY_ALIAS";
private static final String KEY_STORE_FILE_NAME = "KEY_STORE";
private static final String KEY_STORE_PASSWORD = "KEY_STORE_PASSWORD";
@TargetApi(Build.VERSION_CODES.M)
static SecurityKey generateSecretKey(KeyStore keyStore) {
try {
if (!keyStore.containsAlias(KEY_ALIAS)) {
KeyGenerator keyGenerator =
KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT).setBlockModes(
KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(false)
.build());
return new SecurityKey(keyGenerator.generateKey());
}
} catch (KeyStoreException | NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
CommonMethods.printStackTrace(e);
}
try {
final KeyStore.SecretKeyEntry entry =
(KeyStore.SecretKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
return new SecurityKey(entry.getSecretKey());
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException e) {
CommonMethods.printStackTrace(e);
}
return null;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
static SecurityKey generateKeyPairPreM(Context context, KeyStore keyStore) {
try {
if (!keyStore.containsAlias(KEY_ALIAS)) {
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
//1 Year validity
end.add(Calendar.YEAR, 1);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context).setAlias(KEY_ALIAS)
.setSubject(new X500Principal("CN=" + KEY_ALIAS))
.setSerialNumber(BigInteger.TEN)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", ANDROID_KEY_STORE);
kpg.initialize(spec);
kpg.generateKeyPair();
}
} catch (KeyStoreException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchProviderException e) {
CommonMethods.printStackTrace(e);
}
try {
final KeyStore.PrivateKeyEntry entry =
(KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
return new SecurityKey(
new KeyPair(entry.getCertificate().getPublicKey(), entry.getPrivateKey()));
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException e) {
CommonMethods.printStackTrace(e);
}
return null;
}
static SecurityKey generateSecretKeyPre18(Context context) {
try {
KeyStore androidCAStore = KeyStore.getInstance(KeyStore.getDefaultType());
char[] password = KEY_STORE_PASSWORD.toCharArray();
boolean isKeyStoreLoaded = loadKeyStore(context, androidCAStore, password);
KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(password);
if (!isKeyStoreLoaded || !androidCAStore.containsAlias(KEY_ALIAS)) {
//Create and save new secret key
saveMyKeystore(context, androidCAStore, password, protParam);
}
// Fetch Secret Key
KeyStore.SecretKeyEntry pkEntry =
(KeyStore.SecretKeyEntry) androidCAStore.getEntry(KEY_ALIAS, protParam);
CommonMethods.printLog("e", "Secret Key Fetched :" + new String(pkEntry.getSecretKey().getEncoded(), "UTF-8"), EncryptionKeyGenerator.class.getSimpleName());
return new SecurityKey(pkEntry.getSecretKey());
} catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException | UnrecoverableEntryException e) {
CommonMethods.printStackTrace(e);
}
return null;
}
private static boolean loadKeyStore(Context context, KeyStore androidCAStore, char[] password) {
java.io.FileInputStream fis;
try {
fis = context.openFileInput(KEY_STORE_FILE_NAME);
} catch (FileNotFoundException e) {
CommonMethods.printStackTrace(e);
return false;
}
try {
androidCAStore.load(fis, password);
return true;
} catch (IOException | NoSuchAlgorithmException | CertificateException e) {
CommonMethods.printStackTrace(e);
}
return false;
}
private static void saveMyKeystore(Context context, KeyStore androidCAStore, char[] password,
KeyStore.ProtectionParameter protParam)
throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
javax.crypto.SecretKey mySecretKey = KeyGenerator.getInstance("AES").generateKey();
KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey);
androidCAStore.load(null);
androidCAStore.setEntry(KEY_ALIAS, skEntry, protParam);
java.io.FileOutputStream fos = null;
try {
fos = context.openFileOutput(KEY_STORE_FILE_NAME, Context.MODE_PRIVATE);
androidCAStore.store(fos, password);
} finally {
if (fos != null) {
fos.close();
}
}
CommonMethods.printLog("e", "Secret Key Saved : " + new String(mySecretKey.getEncoded(), "UTF-8"), EncryptionKeyGenerator.class.getSimpleName());
}
}
class SecurityKey {
private static final String RSA_MODE = "RSA/ECB/PKCS1Padding";
private static final String AES_MODE_FOR_POST_API_23 = "AES/GCM/NoPadding";
private static final String AES_MODE_FOR_PRE_API_18 = "AES/CBC/PKCS5Padding";
private SecretKey secretKey;
private KeyPair keyPair;
SecurityKey(SecretKey secretKey) {
this.secretKey = secretKey;
}
SecurityKey(KeyPair keyPair) {
this.keyPair = keyPair;
}
String encrypt(String token) {
if (token == null) return null;
try {
Cipher cipher = getCipher(Cipher.ENCRYPT_MODE);
byte[] encrypted = cipher.doFinal(token.getBytes());
return Base64.encodeToString(encrypted, Base64.DEFAULT);
} catch (GeneralSecurityException e) {
CommonMethods.printStackTrace(e);
}
//Unable to encrypt Token
return null;
}
String decrypt(String encryptedToken) {
if (encryptedToken == null) return null;
try {
Cipher cipher = getCipher(Cipher.DECRYPT_MODE);
byte[] decoded = Base64.decode(encryptedToken, Base64.DEFAULT);
byte[] original = cipher.doFinal(decoded);
return new String(original);
} catch (GeneralSecurityException e) {
CommonMethods.printStackTrace(e);
}
//Unable to decrypt encrypted Token
return null;
}
private Cipher getCipher(int mode) throws GeneralSecurityException {
Cipher cipher;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
cipher = Cipher.getInstance(AES_MODE_FOR_POST_API_23);
cipher.init(mode, secretKey, new GCMParameterSpec(128, AES_MODE_FOR_POST_API_23.getBytes(), 0, 12));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
cipher = Cipher.getInstance(RSA_MODE);
cipher.init(mode, mode == Cipher.DECRYPT_MODE ? keyPair.getPublic() : keyPair.getPrivate());
} else {
cipher = Cipher.getInstance(AES_MODE_FOR_PRE_API_18);
cipher.init(mode, secretKey, new IvParameterSpec(new byte[cipher.getBlockSize()]));
}
return cipher;
}
}