I want to encode my Url-params with Base64 and crypt(AES with CFB Mode), but it will not working and I can't get the error. Can someone help me? Here is my code:
private String toBase64Crypt(String cryptString) {
try {
SecretKeySpec key = new SecretKeySpec(pwd.getBytes("UTF8"), "AES");
byte[] cryptByte = cryptString.getBytes("UTF8");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
cryptString = Base64.encodeToString(cipher.doFinal(cryptByte),Base64.DEFAULT);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return cryptString;
}
Related
I encrypted data successfully using the biometric manager flow as shown by google but on trying the decrypt the encrypted data, I keep hitting the IllegalBlockSizeException clause. I need help please.
This is my class that handles all the fingerprint encryption( which works well) but decryption doesn't work, since it keeps hitting the IllegalBlockSizeException clause
public class FingerPrintEncrypter {
private static FingerPrintEncrypter fingerPrintEncrypter;
private static final String ENCRYPTION_BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
private static final String ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
private static final String ENCRYPTION_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
byte[] initVector;
private FingerPrintEncrypter(){
}
public static synchronized FingerPrintEncrypter getInstance(){
if(fingerPrintEncrypter == null){
fingerPrintEncrypter = new FingerPrintEncrypter();
}
return fingerPrintEncrypter;
}
/*
gets the Cipher obj in encryptionMode for encryption tasks.
*/
public Cipher getCipherForEncryption(String aliasKeyName){
try {
Cipher cipher = getCipher();
SecretKey secretKey = getOrCreateSecreteKey(aliasKeyName);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
initVector = cipher.getIV();
return cipher;
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
/*
gets the Cipher obj in decryptionMode for decryption tasks.
*/
public Cipher getCipherForDecryption(String aliasKeyName){
try{
Cipher cipher = getCipher();
SecretKey secretKey = getOrCreateSecreteKey(aliasKeyName);
IvParameterSpec decryptParamSpec = new IvParameterSpec(initVector);
cipher.init(Cipher.DECRYPT_MODE, secretKey, decryptParamSpec);
return cipher;
}catch (InvalidKeyException e){
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
private SecretKey getOrCreateSecreteKey(String aliasKeyName) {
try {
KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
keyStore.load(null);
SecretKey key = ((SecretKey)keyStore.getKey(aliasKeyName, null));
if(key == null){
// key previously create so just grab it
generateSecretKey(aliasKeyName);
}
return key;
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
}
return null;
}
private void generateSecretKey(String aliasKeyName){
try {
// key not create create a new one
KeyGenParameterSpec parameterSpec = new KeyGenParameterSpec.Builder(aliasKeyName,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(ENCRYPTION_BLOCK_MODE)
.setEncryptionPaddings(ENCRYPTION_PADDING)
.setUserAuthenticationRequired(true)
.build();
KeyGenerator keyGenerator = KeyGenerator.getInstance(ENCRYPTION_ALGORITHM, ANDROID_KEY_STORE);
keyGenerator.init(parameterSpec);
keyGenerator.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}
private Cipher getCipher() {
try {
return Cipher.getInstance(ENCRYPTION_ALGORITHM + "/"
+ ENCRYPTION_BLOCK_MODE + "/"
+ ENCRYPTION_PADDING);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
return null;
}
public String encryptData(String info, Cipher cipher){
try {
byte[] encryptedData = cipher.doFinal(info.getBytes("UTF-8"));
return Base64.encodeToString(encryptedData, Base64.NO_WRAP);
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public String decryptData(String stringToDecrypt, Cipher cipher){
try {
return new String(cipher.doFinal(Base64.decode(stringToDecrypt, Base64.NO_WRAP)));
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
}
Here is my encryption method also Decryption method its working fine with Tag Basically server need TAG is it possible server find Tag by my Hex String because every String i send Tag to the server and also with Hex, is it have any other optimal solution
aesKey=context.getString(R.string.aes_key).getBytes();
iv=context.getString(R.string.input_vector).getBytes();
public Map encrypt(String string){
byte[] plainText= new byte[0];
try {
plainText = string.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/GCM/NoPadding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
try {
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(aesKey, "AES"), new IvParameterSpec(iv));
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
byte[] cipherText = new byte[0];
byte[] tag = new byte[0];
try {
cipherText = cipher.doFinal(plainText);
tag= Arrays.copyOfRange(cipherText, cipherText.length -16, cipherText.length);
cipherText= Arrays.copyOfRange(cipherText, 0, cipherText.length -16);
Log.d("testing", "encrypt: "+byteArrayToHexString(tag));
Map<String, Object> map=new HashMap();
map.put("content",byteArrayToHexString(cipherText));
map.put("tag",tag);
Log.d("testing", "encrypt: "+new Gson().toJson(map));
return map;
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return new HashMap();
}
Server need Hex so i convert it into Hex
public String byteArrayToHexString(final byte[] bytes) {
StringBuilder sb = new StringBuilder();
for(byte b : bytes){
sb.append(String.format("%02x", b&0xff));
}
return sb.toString();
}
My Decryption Function is that return me the String i receive Tag and Hex String from the server
public String decrypt(String content,byte[] tag){
byte[] cipherText = hexStringToByteArray(content+byteArrayToHexString(tag));
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/GCM/NoPadding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
try {
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(aesKey, "AES"), new IvParameterSpec(iv));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
byte[] plainText = new byte[0];
try {
plainText = cipher.doFinal(cipherText);
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
try {
Log.d("testing", "encrypt: plain text:"+new String(plainText,"UTF-8"));
return new String(plainText,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
I have the following methods for generating keys and signing the password message.
public void generateKeys() {
try {
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
if (!keyStore.containsAlias(KEY_NAME)) {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, KEYSTORE_NAME);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_SIGN)
.setDigests(KeyProperties.DIGEST_SHA256)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
// Require the user to authenticate with a fingerprint to authorize
// every use of the private key
.setUserAuthenticationRequired(true)
.build());
keyPairGenerator.generateKeyPair();
}
loadKeys();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public BiometricPrompt.CryptoObject getCryptoObject() {
cryptoObject = new BiometricPrompt.CryptoObject(signature);
return cryptoObject;
}
private void loadKeys() {
try {
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
if (keyStore.containsAlias(KEY_NAME)) {
publicKey = keyStore.getCertificate(KEY_NAME).getPublicKey();
privateKey = (PrivateKey) keyStore.getKey(KEY_NAME, null);
signature = Signature.getInstance(Constants.SIGNATURE);
signature.initSign(privateKey);
}
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
public String sign(String inputStr) {
try {
Signature signature = cryptoObject.getSignature();
signature.update(inputStr.getBytes());
byte[] signedBytes = signature.sign();
String result = HexManager.bytesToHex(signedBytes);
Log.d("TAG", result);
return result;
} catch (SignatureException e) {
e.printStackTrace();
}
return null;
}
After that, I saved the signed password in Shared Preferences. Later, I want to verify the saved password with a new password that is verified with the fingerprint.
Here is my method to verify:
public boolean verify(String inputStr, String savedStr) {
try {
Signature signature = cryptoObject.getSignature();
signature.initVerify(publicKey);
signature.update(inputStr.getBytes());
boolean isVerified = signature.verify(savedStr.getBytes());
return isVerified;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return false;
}
But it always return false.
Does anybody knows why?
It looks like in your sign() method you're returning the Hex of the byte[] obtained from the signature.sign() method. If this is what you're saving as savedStr. Then the verification method should be changed to convert the Hex encoded string to a byte[]. You could use HexManager.hexToBytes() (or equivalent) if it exists to convert the savedStr to a byte[] savedStrBytes.
public boolean verify(String inputStr, String savedStr) {
try {
byte[] savedStrBytes = HexManager.hexToByes(savedStr);
Signature signature = cryptoObject.getSignature();
signature.initVerify(publicKey);
signature.update(inputStr.getBytes());
boolean isVerified = signature.verify(savedStrBytes);
return isVerified;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return false;
}
I have some token and I need first to sign it with SHA256 and ECDSA based on private and public key from KeyStore.
Every time when I try to verify value I get false as result. I do not know why.
Does someone have any idea how to solve this?
Here are my functions to generate and load keys:
private void generateKeys(){
try {
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
if(!keyStore.containsAlias(KEY_NAME)) {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, KEYSTORE_NAME);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
.setDigests(KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA512)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
.setUserAuthenticationRequired(false)
.build());
keyPairGenerator.generateKeyPair();
setRegistred(true);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadKeys(){
try {
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
if(keyStore.containsAlias(KEY_NAME)) {
publicKey = keyStore.getCertificate(KEY_NAME).getPublicKey();
privateKey = (PrivateKey) keyStore.getKey(KEY_NAME, null);
}
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
}
}
This is how sign value:
public String sign(String inputStr, FingerprintManager.CryptoObject cryptoObject){
try {
Signature signature = Signature.getInstance(SecurityConstants.SIGNATURE);
signature.initSign(privateKey);
signature.update(inputStr.getBytes());
byte[] signedBytes = signature.sign();
String result = Base64.encodeToString(signedBytes, Base64.DEFAULT);
Log.d("TAG", result);
return result;
} catch (SignatureException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
Here is my try to verify with Public Key:
public boolean verifyWithPublicKey(String input, FingerprintManager.CryptoObject cryptoObject){
try {
Signature signature = Signature.getInstance(SecurityConstants.SIGNATURE);
keyStore = KeyStore.getInstance(KEYSTORE_NAME);
keyStore.load(null);
PublicKey pk = getPublicKeyForVerification();
signature.initVerify(pk);
signature.update(input.getBytes());
boolean isVerifed = signature.verify(input.getBytes());
Log.d("TAG", String.valueOf(isVerifed));
return isVerifed;
} catch (SignatureException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
The error is here, when you write the following code to verify the signature:
signature.update(input.getBytes());
boolean isVerifed = signature.verify(input.getBytes());
With this code, you try to verify that the signature has been signed with itself!
You should have:
signature.update(MY_BYTES_ARRAY_OF_DATA);
boolean isVerifed = signature.verify(MY_SIGNATURE);
Do not forget that the signature does not encapsulate the signed data by default.
If you want to have a format that includes signed data and associated signature, use S/MIME, OpenPGP, etc.
This question already has an answer here:
Problems outsourcing RSA encryption and decryption
(1 answer)
Closed 9 years ago.
i'm developing an android app. Unfortunately i have a compatibility problem. My source code works with firmware 4.1, but crashes with devices with firmware 2.2. The error seems to be a "ClassNotFoundException" caused by the ObjectInputStream.
My sourcecode for the encryption and decryption:
private Key getPublicKey() {
try {
InputStream fis = activity.getResources().openRawResource(R.raw.publick);
ObjectInputStream ois = new ObjectInputStream(fis);
Key RSApublicKey = (Key) ois.readObject();
return RSApublicKey;
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private Key getPrivateKey() {
try {
InputStream fis = activity.getResources().openRawResource(R.raw.privatek);
ObjectInputStream ois = new ObjectInputStream(fis);
Key RSAprivateKey = (Key) ois.readObject();
return RSAprivateKey;
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e) {
Log.e("error", "Error: " + e);
e.printStackTrace();
}
return null;
}
public byte[] encrypt(String data) {
byte[] encrypted = null;
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey());
encrypted = cipher.doFinal(data.getBytes());
}
catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
catch (BadPaddingException e) {
e.printStackTrace();
}
catch (InvalidKeyException e) {
e.printStackTrace();
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (NoSuchPaddingException e) {
e.printStackTrace();
}
catch (NoSuchProviderException e) {
e.printStackTrace();
}
return encrypted;
}
public String decrypt(byte[] encrypted) {
byte[] decrypted = null;
try {
Cipher cipher;
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
decrypted = cipher.doFinal(encrypted);
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (NoSuchPaddingException e) {
e.printStackTrace();
}
catch (InvalidKeyException e) {
e.printStackTrace();
}
catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
catch (BadPaddingException e) {
e.printStackTrace();
}
catch (NoSuchProviderException e) {
e.printStackTrace();
}
return new String(decrypted);
}
The error in logcat:
03-23 10:13:19.706: E/Error(427): Error: java.lang.ClassNotFoundException: com.android.org.bouncycastle.jce.provider.JCERSAPrivateCrtKey
Do you have any ideas, how i could get it work with android 2.2?
You are better off using the Key.getEncoded() method to serialize the key. The Key.getFormat() already hints that RSA private keys should default to PKCS#8 encoding.
You can then use the PKCS8EncodedKeySpec class and an instance of an "RSA" KeyFactory to deserialize the resulting byte array.
The serialized keys may not work correctly over different implementations of PrivateKey (as you've already found out by now), and PKCS#8 is a well defined and often used standard.
Well, if it works on 4.1+ but not on 2.2, I guess it's a class from android that has been included after 2.2. You can test this by trying to compile with android 2.2 a project that uses this class and see if you can. If this is the case just find it and include it in your project.