Why always give me false in signature? - java

I try in this code to verify my code, I have public key , my data and signature.I am read my signature from file and convert my string to public key then get my data and verify to signature.
public static boolean verify () {
String publickey = "MIGfMA0GCSqGSIb3DQE";
byte[] encKey = Base64.decodeBase64(publickey.getBytes());
try {
byte[] MACaddress = GetData();
BufferedReader in = new BufferedReader(new FileReader(
"EndSignatuer.txt"));
FileInputStream keyfis = new FileInputStream("EndSignatuer.txt");
byte[] Signen = new byte[keyfis.available()];
keyfis.read(Signen);
keyfis.close();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pubKey);
byte[] deSignen = Base64.decodeBase64(Signen);
byte[] decrypted_digest = cipher.doFinal(deSignen);
MessageDigest md5_digest = MessageDigest.getInstance("MD5");
md5_digest.update(MACaddress);
byte[] digest = md5_digest.digest();
if (decrypted_digest == digest) {
return true;
}else {
return false;//her why give me false
}
Code encryption:
public static void GenarationKEY(byte[] data) {
try {
File fileEndSignatuer = new File("EndSignatuer.txt");
FileOutputStream fopEndSignatuer = new FileOutputStream(
fileEndSignatuer);
// /Read private key from file
FileInputStream keyfis = new FileInputStream("PiveteKey.txt");
byte[] PrivateKeyB = new byte[keyfis.available()];
keyfis.read(PrivateKeyB);
keyfis.close();
byte[] decodePrivetekey = Base64.decodeBase64(PrivateKeyB);
// /get private key
PKCS8EncodedKeySpec pubKeySpec = new PKCS8EncodedKeySpec(
decodePrivetekey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privKey = keyFactory.generatePrivate(pubKeySpec);
// / make hash
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privKey);
// /make encoding
MessageDigest md5_digest = MessageDigest.getInstance("MD5");
byte[] digest = md5_digest.digest(data);
byte[] cipherText = cipher.doFinal(digest);
byte[] degnatureencode = Base64.encodeBase64(cipherText);
fopEndSignatuer.write(degnatureencode);
fopEndSignatuer.flush();
fopEndSignatuer.close();
}

First of all, what you do is not quite RSA digital signature. Use Signature class instead of combination Cipher and MessageDigest. Or if you insist to do it on low level, then consult specification, particularly section 9.2.
Secondly, string MIGfMA0GCSqGSIb3DQE doesn't represent RSA public key neither it is proper Base64-encoded data.
Also you want to use Arrays.equals(byte[], byte[]) instead of equality operator, as the latter just ensures that array object is the same, while the former compares actual content of the arrays.

Related

Java Android - Encrypt/Decrypt file contents

So at the moment I'm trying to write some encrypted text to a file and then be able to read that back in, decrypt it and display it to the user. I'm currently using AES-256 with PBKDF2 password derivation as I'd like to be able to use a user's password to encrypt/decrypt the files. The files are simple text files. The code I am currently using to encrypt some text and save it to a file is below. As far as I can tell, from having a look using adb, this works correctly.
FileOutputStream out = new FileOutputStream(mypath);
String defaultMessage = "Empty File";
int iterationCount = 1000;
int keyLength = 256;
int saltLength = keyLength / 8;
SecureRandom randomGenerator = new SecureRandom();
byte[] salt = new byte[saltLength];
randomGenerator.nextBytes(salt);
KeySpec keySpec = new PBEKeySpec(submittedPassword.toCharArray(), salt, iterationCount, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
randomGenerator.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
byte[] ciphertext = cipher.doFinal(defaultMessage.getBytes("UTF-8"));
String finalMessage = ciphertext.toString() + "]" + iv.toString() + "]" + salt.toString();
out.write(finalMessage.getBytes());
out.close();
P.S The above is within a Try/Except.
The code below is what I'm currently trying to use to read in the file and then decrypt it, however, when I try to display the decrypted contents via the test view at the end, it does not show up.
FileInputStream fileInputStream = new FileInputStream(mypath);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuffer stringBuffer = new StringBuffer();
while ((fileContents = bufferedReader.readLine()) != null) {
stringBuffer.append(fileContents + "\n");
}
String fileContentsString = stringBuffer.toString();
String[] fileContentsList = fileContentsString.split("]");
byte[] cipherText = fileContentsList[0].getBytes();
Toast.makeText(getApplicationContext(), fileContentsList[0], Toast.LENGTH_LONG).show();
byte[] iv = fileContentsList[1].getBytes();
byte[] salt = fileContentsList[2].getBytes();
KeySpec keySpec = new PBEKeySpec(submittedPassword.toCharArray(), salt, 1000, 256);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivParams);
byte[] plaintext = cipher.doFinal(cipherText);
String plainrStr = new String(plaintext , "UTF-8");
textEdit.setText(plainrStr);
Hopefully someone can provide me with some assistance here. Again, the second code segment is within a Try/Except statement.
You have multiple problems with your code.
Encryption
This code
String finalMessage = ciphertext.toString() + "]" + iv.toString() + "]" + salt.toString();
does not produce a ciphertext. See here: Java: Syntax and meaning behind "[B#1ef9157"? Binary/Address?
The IV and salt have fixed sizes, so they can be placed in front of the ciphertext. After you've written the whole ciphertext, you need to use something like Base64 or Hex in order to get a String. Modern ciphers like AES produce ciphertexts that can contain bytes of any value which don't always constitute valid character encodings such as UTF-8. Strings are no containers for arbitrary byte[] contents.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(iv);
baos.write(salt);
baos.write(ciphertext);
String finalMessage = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
But you don't need that at all, because you can directly write your ciphertext into the file:
out.write(iv);
out.write(salt);
out.write(ciphertext);
Decryption
Don't use InputStreamReader, a BufferedReader and a StringBuffer for binary data. Otherwise, you'll corrupt your binary ciphertext.
You only need this:
byte[] iv = new byte[16];
byte[] salt = new byte[32];
byte[] ctChunk = new byte[8192]; // not for whole ciphertext, just a buffer
if (16 != fileInputStream.read(iv) || 32 != fileInputStream.read(salt)) {
throw new Exception("IV or salt too short");
}
KeySpec keySpec = new PBEKeySpec(submittedPassword.toCharArray(), salt, 1000, 256);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivParams);
int read;
ByteArrayOutputStream ctBaos = new ByteArrayOutputStream();
while((read = fileInputStream.read(ctChunk)) > 0) {
ctBaos.write(cipher.update(cipherText, 0, read));
}
ctBaos.write(cipher.doFinal());
String plainrStr = new String(ctBaos.toByteArray(), "UTF-8");
textEdit.setText(plainrStr);
This handles randomization properly but doesn't provide integrity. If you want to detect (malicious) manipulations of your ciphertexts (and generally you'll want that to prevent some attacks), you'd need to use an authenticated mode like GCM or EAX, or employ an encrypt-then-MAC scheme with a strong MAC like HMAC-SHA256.
Use a library like tozny/java-aes-crypto in order to use good defaults.
How to write some encrypted text to a file and then be able to read that back in?
public static byte[] generateKey(String password) throws Exception
{
byte[] keyStart = password.getBytes("UTF-8");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(keyStart);
kgen.init(128, sr);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
public static byte[] encodeFile(byte[] key, byte[] fileData) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(fileData);
return encrypted;
}
public static byte[] decodeFile(byte[] key, byte[] fileData) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(fileData);
return decrypted;
}
To save a encrypted file to sd do:
File file = new File(Environment.getExternalStorageDirectory() + File.separator + "your_folder_on_sd", "file_name");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] yourKey = generateKey("password");
byte[] filesBytes = encodeFile(yourKey, yourByteArrayContainigDataToEncrypt);
bos.write(fileBytes);
bos.flush();
bos.close();
To decode a file use:
byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);
For reading in a file to a byte Array there a different way out there. A Example: http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/

Java: write and read password based encrypted private key

I am trying to read a password based encrypted private key from a file, but I'm getting the following exception:
java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
at sun.security.util.DerInputStream.getLength(DerInputStream.java:561)
at sun.security.util.DerValue.init(DerValue.java:365)
at sun.security.util.DerValue.<init>(DerValue.java:294)
at javax.crypto.EncryptedPrivateKeyInfo.<init>(EncryptedPrivateKeyInfo.java:84) ...
This is how I encrypt and write to file the private key:
public static void savePrivateKeyToDisk(PrivateKey privateKey, String passord){
try {
// unencrypted PKCS#8 private key
byte[] encodedPrivateKey = privateKey.getEncoded();
String MYPBEALG = "PBEWithSHA1AndDESede";
int count = 20;
SecureRandom random = new SecureRandom();
byte[] salt = new byte[8];
random.nextBytes(salt);
// Create PBE parameter set
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(MYPBEALG);
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
Cipher pbeCipher = Cipher.getInstance(MYPBEALG);
// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
// Encrypt the encoded Private Key with the PBE key
byte[] cipherText = pbeCipher.doFinal(encodedPrivateKey);
// Now construct PKCS #8 EncryptedPrivateKeyInfo object
AlgorithmParameters algparms = AlgorithmParameters.getInstance(MYPBEALG);
algparms.init(pbeParamSpec);
EncryptedPrivateKeyInfo encinfo = new EncryptedPrivateKeyInfo(algparms, cipherText);
// DER encoded PKCS#8 encrypted key
byte[] encryptedPkcs8 = encinfo.getEncoded();
File encryptedPrivate = new File(PRIVATE_KEY_FILE);
if (encryptedPrivate.getParentFile() != null) {
encryptedPrivate.getParentFile().mkdirs();
}
encryptedPrivate.createNewFile();
ObjectOutputStream publicKeyOS = new ObjectOutputStream(
new FileOutputStream(encryptedPrivate));
publicKeyOS.writeObject(encryptedPkcs8);
publicKeyOS.close();
}
catch (Exception e){
e.printStackTrace();
}
}
... and this is how I'm trying to read the encrypted private key:
public static PrivateKey getPrivateKey(String passwd){
try {
byte[] encodedPrivateKey = getFileBytes(PRIVATE_KEY_FILE);
// exception thrown from here
EncryptedPrivateKeyInfo encryptPKInfo = new EncryptedPrivateKeyInfo(encodedPrivateKey);
Cipher cipher = Cipher.getInstance(encryptPKInfo.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray());
SecretKeyFactory secFac = SecretKeyFactory.getInstance(encryptPKInfo.getAlgName());
Key pbeKey = secFac.generateSecret(pbeKeySpec);
AlgorithmParameters algParams = encryptPKInfo.getAlgParameters();
cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
KeySpec pkcs8KeySpec = encryptPKInfo.getKeySpec(cipher);
KeyFactory kf = KeyFactory.getInstance(ALGORITHM);
return kf.generatePrivate(pkcs8KeySpec);
}
catch (Exception e){
e.printStackTrace();
return null;
}
}
... the getFileBytes method:
private static byte[] getFileBytes(String infile){
File f = new File(infile) ;
int sizecontent = ((int) f.length());
byte[] data = new byte[sizecontent];
try
{
FileInputStream freader = new FileInputStream(f);
freader.read(data, 0, sizecontent) ;
freader.close();
return data;
}
catch(IOException ioe)
{
System.out.println(ioe.toString());
return null;
}
}
It seems like the encrypted private key is not in the right format, but I save it in DER PKCS#8 format.
So, the question: What is the mistake in this code?
I guess the problem is that you write an Object, but then you read byte[] (not an Object)
I would suggest that you either read the whole object and then get the required bytes or even better write byte[] directly (don't use ObjectOutputStream) and then load these bytes, eg:
FileOutputStream fos = new FileOutputStream(PRIVATE_KEY_FILE);
fos.write(myByteArray);
fos.close();
and then to retrieve it:
byte[] bytes = Files.readAllBytes(Paths.get(PRIVATE_KEY_FILE));

.NET equivalent of Java KeyFactory.getInstance "RSA"/"RSA/ECB/PKCS1Padding"

I have the following code,
public static String encrypt(String plainText, String key){
try{
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decode(key, Base64.DEFAULT)));
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeToString(cipher.doFinal(plainText.getBytes("UTF-8")),Base64.DEFAULT);
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
I want to convert this to C#. I have tried CryptUtils but it doesn't work https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/CryptUtils.cs
Sample key,
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ9AMIIBCgKCAQEAoqB1N9kugk4UKYnbh0fcg3qYyYKP0m4B
MjWd05ReeAdj+7JRYDEKO6xthDdVSdRO1/2V+YtY8DnXWnxRaICwu8235s3imZCyqgYnomPWdY+F
K540oTz/zug+9wbrlzt/WQFUU4lPlQbzm/Gjw8XfaCozT0e3bnWQcD7rORCOyuJgwSGgREjTv1ss
pgEaKTMknii9vpGZLeAXwoeIYROhuT4IoIkPDhtY0/UZiCi6v7Ja2dmy53VlWIkcm3rcnSJdvpXr
OgiHvaNABHmeymNycNqd6WUaysBRheluQ86nq/2nZPW0gcvmYt5zbMMYX3yY/n2WtAKeNQBAEW1q
b0s6MwIDAQAB
Possible encryped value,
Y3VTjghDnTrCeG8C/RklKsJ3Y0Mt89sSGGin28E4iQPQvKqeZBws7rBQEZaRamDWftxCkEYZs4Qh
V2l4IVlrawdtRmQlcQh8McrpqP/97Gz8pEDEYnqA7kqBTqZw0Z5o0WsshGSwiAQ9wNSym4xHejkq
zrKxWP8XCMkcT0NlKlRMoqKKICFKZbqWeSQkQM5y9OEcmB6inNNkJCoM1Ip48+cK3cOE6dqXNVrl
sSTZ8WQKwoB3dJmcYqexR3kAvBYdX6ZxEF+2+6b9h8+tc5G7Y5R2eqycyUossdkCcI3fNVhyc72P
axCjZFWZUgfDGCxg1WNhStrH9L8c59P35JKKug==
Since i don't have the private key, i can't decrypt, but at least this produces the right lengthed values.
So try this (you need bouncycastle for reading pem):
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
var keyBytes =
Convert.FromBase64String(
"MIIBI...."); // your key here
AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(keyBytes);
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter;
RSAParameters rsaParameters = new RSAParameters();
rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);
byte[] plaintext = Encoding.UTF8.GetBytes("amount=1&currency=AED");
byte[] ciphertext = rsa.Encrypt(plaintext, false);
string cipherresult = Convert.ToBase64String(ciphertext);

Invalid Cipher bytes in Encryption method in Android using RSA

We are facing an issue while trying to Encrypt data in Android and Decrypt it in a WCF Service. The Android code to encrypt data is as follows:
try{
String strModulus = "tr82UfeGetV7yBKcOPjFTWs7pHqqr/5YKKWMUZ/HG4HnCmWrZsOhuR1FBnMZ/g2YiosoSlu0zd7Ukz9lX7wv2RLfWXfMvZYGpAAvfYWwzbyQ2i1q+tKE/thgKNscoSRellDD+uJcYn1H4hnaudVyYJH9miVhOKhKlExMzw8an6U=";
String strExponent = "AQAB";
byte[] modulusBytes = Base64.decode(strModulus, Base64.DEFAULT);
byte[] exponentBytes = Base64.decode(strExponent, Base64.DEFAULT);
BigInteger modulus = new BigInteger(1, modulusBytes );
BigInteger exponent = new BigInteger(1, exponentBytes);
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA/ECB/PKCS1Padding");
PublicKey pubKey = fact.generatePublic(rsaPubKey);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] plainBytes = new String("Manchester United").getBytes("UTF-8");
byte[] cipherData = cipher.doFinal(plainBytes);
encryptedString = Base64.encodeToString(cipherData, Base64.DEFAULT);
}
catch(Exception e){
Log.e("Error", e.toString());
}
return encryptedString;
The same code in Java:
try{
String strModulus = "tr82UfeGetV7yBKcOPjFTWs7pHqqr/5YKKWMUZHG4HnCmWrZsOhuR1FBnMZ/g2YiosoSlu0zd7Ukz9lX7wv2RLfWXfMvZYGpAAvfYWwzbyQ2i1q+tKE/thgKNscoSRellDD+uJcYn1H4hnaudVyYJH9miVhOKhKlExMzw8an6U=";
String strExponent = "AQAB";
byte[] modulusBytes = DatatypeConverter.parseBase64Binary("tr82UfeGetV7yBKcOPjFTWs7pHqqr/5YKKWMUZ/HG4HnCmWrZsOhuR1FBnMZ/g2YiosoSlu0zd7Ukz9lX7wv2RLfWXfMvZYGpAAvfYWwzbyQ2i1q+tKE/thgKNscoSRellDD+uJcYn1H4hnaudVyYJH9miVhOKhKlExMzw8an6U=");
byte[] exponentBytes = DatatypeConverter.parseBase64Binary("AQAB");
BigInteger modulus = new BigInteger(1, modulusBytes );
BigInteger exponent = new BigInteger(1, exponentBytes);
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(rsaPubKey);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] plainBytes = new String("Manchester United").getBytes("UTF-8");
byte[] cipherData = cipher.doFinal(plainBytes);
//String encryptedString = Base64.encodeToString(cipherData, Base64.NO_PADDING);
String encryptedString = DatatypeConverter.printBase64Binary(cipherData);
String encryptedData = encryptedString;
}
catch(Exception e){
}
}
WCF Service:
public string Decrypt()
{
const int PROVIDER_RSA_FULL = 1;
const string CONTAINER_NAME = "Tracker";
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(cspParams);
rsa1.FromXmlString("<RSAKeyValue><Modulus>tr82UfeGetV7yBKcOPjFTWs7pHqqr/5YKKWMUZ/HG4HnCmWrZsOhuR1FBnMZ/g2YiosoSlu0zd7Ukz9lX7wv2RLfWXfMvZYGpAAvfYWwzbyQ2i1q+tKE/thgKNscoSRellDD+uJcYn1H4hnaudVyYJH9miVhOKhKlExMzw8an6U=</Modulus><Exponent>AQAB</Exponent><P>6e0nv7EBFBugtpoB+ozpg1J4js8E+DVyWCuBsERBPzqu4H7Z/oeLIRSC8Gi5GZgrCpBf3EvyIluM7rzaIfNThQ==</P><Q>x/29X9ns1WcXC42IJjLDjscz5ygdVh79dm8B2tQVbqwyhDsQ6OIOQdu5+eHf4hUMoTrM9KkS2F6FGlLXuaOFoQ==</Q><DP>kTS2LMaJ/dpce5zDx6w6s1q5HSSiWBSNIu/2s9zah448yXvUg6vNkD40PVk0NRAA/7C44H2AExWzOOqfmN17JQ==</DP><DQ>xtAx9drQPWnpl/uQUOEAVa0kpPTVDStrr9Q1FNTnpYkcAyYw7kLkB4anAIoSpk9kqdeprsNxz5VPXtbiTFMKYQ==</DQ><InverseQ>O0594NMjnjSp+/NAa1kQxoQNzn1qqq+p1Zb+kT3/jRc/0d7ZnqSSpxFMXfxx3yZkNAOPDOdbckPQbRZ13RKBHg==</InverseQ><D>bjVEagwvkrZaTt9CTW1hd3362weLFlX6DpE/3R3RcrpVfkSwKGpEhqGrNeeGPlsuqiaf5rAFir4eTqrF1QVliKsU4XE0RyzP5lHGc7dlX4DOHMjs2R9nNWv8QOTPoaRuLrLGorqBXlw/jQPxFI6gQzkIIjzuf//lDVnFam3dw4E=</D></RSAKeyValue>");
string data2Decrypt = "LyVNDhkdJ5jNgwZDiVZ1R0lmd10AQgqNDFHh2vJB1676eg8wj0MOdTyChAGrvEjha0uXg+f/aNBAc4+/LFbCgsA1e+O3wnXr27sXznGJ9G15avZzQHG4JWUS42MXBahAkcJ80pcihTbL9edfQCkEuj9RzQ/zFJyDEMssfd/EPDM=";
byte[] encyrptedBytes = Convert.FromBase64String(data2Decrypt);
byte[] plain = rsa1.Decrypt(encyrptedBytes, false);
string decryptedString = System.Text.Encoding.UTF8.GetString(plain);
}
Original Data : 'Manchester United'
The strange thing is that if I encrypt a string with the Java code it can be decrypted at the WCF service end, however, if it is encrypted using the above Android code, the decryption provides the error: "The data to be decrypted exceeds the maximum for this modulus of 128 bytes".
On debugging, I realized that the byte[] cipherData is not the same for Android and Java. All the previous values happen to be in sync. This generates different Encrypted Strings in Java and Android.
My question is why does this happen? Is there a silly mistake? Is there a way to work around it? Or something else that can be done in Android to get the 'Cipher Data' right?
Any help will be appreciated.
You are using a different padding on Android. Use the exact same padding on Android as well:
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

Can't restore privateKey RSA

I have this issue about java cryptography.
I take a password from the user then I product a private key and a public key.From the public key I create the cipher and then I store the private key and the cipher.
Then from my second application I read the password again from the user , the cipher file and the private key and then I try to match the password with the decryption of the cipher and the private Key.
My first application:
private static byte[] encrypt(byte[] inpBytes, PublicKey key,
String xform) throws Exception {
Cipher cipher = Cipher.getInstance(xform);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(inpBytes);
}
String xform = "RSA";
// Generate a key-pair
KeyPairGenerator kpg = null;
try {
kpg = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Efarmogi_1.class.getName()).log(Level.SEVERE, null, ex);
}
kpg.initialize(512); // 512 is the keysize.
KeyPair kp = kpg.generateKeyPair();
/create public and private key
PublicKey pubk = kp.getPublic();
PrivateKey prvk = kp.getPrivate();
//password from user
String password = T_Password.getText();
byte[] dataBytes = password.getBytes();
//create cipher
byte[] encBytes = null;
try {
encBytes = encrypt(dataBytes, pubk, xform);
} catch (Exception ex) {
Logger.getLogger(Efarmogi_1.class.getName()).log(Level.SEVERE, null, ex);
}
//storing
//cipher
FileOutputStream cipher = null;
try {
cipher = new FileOutputStream( "Xrhstes\\"+T_Username.getText()+"\\hash_"+T_Username.getText());
cipher.write(encBytes);//write with bytes
cipher.close();
} catch (IOException ex) {
Logger.getLogger(Efarmogi_1.class.getName()).log(Level.SEVERE, null, ex);
}
//private key
byte[] key2 = prvk.getEncoded();
FileOutputStream keyfos2 = null;
try {
keyfos2 = new FileOutputStream("Xrhstes\\"+T_Username.getText()+"\\private_"+ T_Username.getText()+".pem");
keyfos2.write(key2);
keyfos2.close();
and this is the second application:
private static byte[] decrypt(byte[] inpBytes, PrivateKey key,String xform) throws Exception{
Cipher cipher = Cipher.getInstance(xform);
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(inpBytes);
}
//fetch private key
byte[] prvk1 = new byte[(int)new File("C:\\...\\"+T_Username.getText()+"\\private_"+ T_Username.getText()).length()];
//make it from bytes to private key
KeyFactory kf= KeyFactory.getInstance("RSA");
PrivateKey prvk=kf.generatePrivate(new PKCS8EncodedKeySpec(prvk1));
//fetch cipher
byte[] encBytes = new byte[(int)new File("C:\\...\\"+T_Username.getText()+"\\hash_"+ T_Username.getText()).length()];
//decrypt with our password given from user
String xform = "RSA";
byte[] decBytes = decrypt(encBytes,prvk, xform);
boolean expected = java.util.Arrays.equals(password, decBytes);
System.out.println("Test " + (expected ? "SUCCEEDED!" : "FAILED!"));
My issue is when I try to retransform the bytes saved , back to privateKey I get multiple errors that key type is invalid(problem starts at decoding PKCS8EncodedKeySpec it is noted that KeySpec is invalid).I tried numerous ways but still the same,could someone guide me where is my mistake ? thanks in advance!!!
With the following lines:
byte[] prvk1 = new byte[(int)new File("C:\\...\\"+T_Username.getText()+"\\private_"+ T_Username.getText()).length()];
and
byte[] encBytes = new byte[(int)new File("C:\\...\\"+T_Username.getText()+"\\hash_"+ T_Username.getText()).length()];
You actually create two empty byte arrays. You only indicate the size of the array using File.length(), which obviously is not correct. Try again after actually reading the files, e.g. using the readAllBytes method (requires Java 8 or higher).

Categories