I plan to use ECC encryption in iOS and Android,and decrypt in server.iOS uses objective-C,Android and Server use Java.In iOS,I use CryptoppECChttps://github.com/SandeepAggarwal/CryptoppECC,encryption and decryption can be successful. The server can also encrypt and decrypt successfully by using Java. However, when I decrypt the encrypted data of IOS on the server, it will fail.
iOS:
- (void)eccCryptForShortKey{
NSString *publicKey = #"AvWy7WANZcn0ea1Li2AJCjo=";
NSString *privateKey = #"ANqNuiMahQziTilCGa2bA3A=";
NSString *str = #"hello world";
CurveType curveType = CurveType_secp128r1;
CryptoppECC *ecc = [[CryptoppECC alloc] init];
// encrypt
NSString *enStr =[ecc encrypt:str :publicKey curve:curveType];
// decrypt
NSString*deStr = [ecc decrypt:enStr :privateKey curve:curveType];
if (deStr.length == 0) {
NSLog(#"\n===Fail");
}else{
NSLog(#"\n===Succ: %#",deStr);
}
}
Java:
public class EccCryptopp{
public static final String curve = "secp128r1";
private static final String CIPHER = "ECIES";
private static final String ALGRITHM = "ECDSA";
private static final String PROVIDER = "BC";
private static final String publicKeyStrShort = "AvWy7WANZcn0ea1Li2AJCjo=";
private static final String privateKeyStrShort = "ANqNuiMahQziTilCGa2bA3A=";
static{
Security.insertProviderAt(new BouncyCastleProvider(), 1);
}
public static void test() {
//the data encrypted in iOS
String encryptData = "BO1QGnFjDNVQ3rmcVhKJDZuYJl427Pbgt2lv9PvQ3ifXwDjKG/XcdqG5Mu1FEVahifhyXrtQEgvDUP1T0kjk0w==";
String decryptData = decryptDataWithShortKey(encryptData, privateKeyStrShort);
int dLength = decryptData.length();
if (dLength == 0) {
System.out.println("decrypt fail");
} else {
System.out.println("decrypt data:" + dLength);
System.out.println(decryptData);
}
}
private static byte[] base64Decode(String s){
return Base64.getDecoder().decode(s);
}
public static PublicKey loadPublicKeyWithShort(String curve, byte[] data)
throws GeneralSecurityException {
KeyFactory factory = KeyFactory.getInstance(ALGRITHM, PROVIDER);
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curve);
ECCurve eccCurve = spec.getCurve();
EllipticCurve ellipticCurve = EC5Util.convertCurve(eccCurve, spec.getSeed());
java.security.spec.ECPoint point = ECPointUtil.decodePoint(ellipticCurve, data);
java.security.spec.ECParameterSpec params = EC5Util.convertSpec(ellipticCurve, spec);
ECPublicKeySpec keySpec = new ECPublicKeySpec(point, params);
return factory.generatePublic(keySpec);
}
public static PrivateKey loadPrivateKeyWithShort(String curve, byte[] data)
throws GeneralSecurityException {
KeyFactory factory = KeyFactory.getInstance(ALGRITHM, PROVIDER);
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curve);
ECCurve eccCurve = spec.getCurve();
EllipticCurve ellipticCurve = EC5Util.convertCurve(eccCurve, spec.getSeed());
java.security.spec.ECParameterSpec params = EC5Util.convertSpec(ellipticCurve, spec);
ECPrivateKeySpec keySpec = new ECPrivateKeySpec(new BigInteger(1, data), params);
return factory.generatePrivate(keySpec);
}
public static String encryptDataWithShortKey(String token, String publicKeyShort) {
try {
PublicKey publicKey = loadPublicKeyWithShort(curve, base64Decode(publicKeyShort));
Cipher c = Cipher.getInstance(CIPHER);
c.init(Cipher.ENCRYPT_MODE, publicKey);
String messageString = token;
byte[] message = messageString.getBytes();
byte[] cipher = c.doFinal(message);
return Base64.getEncoder().encodeToString(cipher);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decryptDataWithShortKey(String message,String private_key) {
try {
PrivateKey privateKey = loadPrivateKeyWithShort(curve, base64Decode(private_key));
Cipher c = Cipher.getInstance(CIPHER);
byte[] token = ((Base64.getDecoder().decode(message.getBytes())));
c.init(Cipher.DECRYPT_MODE, privateKey);
byte[] plaintext = c.doFinal(token);
return new String(plaintext);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.58</version>
</dependency>
When the encrypted content of IOS is obtained and decrypted,it's always exception.
enter image description here
org.bouncycastle.jcajce.provider.util.BadBlockException: unable to process block
at org.bouncycastle.jcajce.provider.asymmetric.ec.IESCipher.engineDoFinal(Unknown Source)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2207)
at com.nonce.crypto.ecc.EccCryptopp.decryptDataWithShortKey(EccCryptopp.java:165)
at com.nonce.crypto.ecc.EccCryptopp.test(EccCryptopp.java:59)
at com.nonce.crypto.ecc.ECC.testEccCryptopp(ECC.java:38)
at com.nonce.crypto.ecc.ECC.main(ECC.java:23)
Caused by: org.bouncycastle.crypto.InvalidCipherTextException: invalid MAC
at org.bouncycastle.crypto.engines.IESEngine.decryptBlock(Unknown Source)
at org.bouncycastle.crypto.engines.IESEngine.processBlock(Unknown Source)
... 6 more
I don't know whether it's Java decryption or IOS encryption.
This problem is not limited for inter-system operation. I see the same problem between different versions of bouncy castle on the java platform. Specifically
bcprov Version 1.52 AND
bcprov Version 1.68
Something seems to have changed between both versions in elliptic curve implementation. I am still in the process of dig deeper.
So i found the answer to my problem and probably yours.
BouncyCastle changed the ECIES implementation between 1.52 and 1.53:
ECIES/IES was only using a 4 byte label length for the MAC tag when it should have been an 8 byte one. This has now been fixed and OldECIES/OldIES has been added for backwards compatibility.
check https://www.bouncycastle.org/releasenotes.html
So most likely you are trying to use different implementations (=versions) with encrypt/decrypt.
Related
I'm trying to convert this java code:
package ffsd;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class GatewayEncryptUtil {
public static String encrypt(String plainText, String key) throws Exception {
return new String(Base64.getEncoder().encode(doCrypt(plainText.getBytes(), 1, key)));
}
public static byte[] doCrypt(byte[] inputText, int operation, String key) throws Exception {
MessageDigest mDigest = MessageDigest.getInstance("SHA-512");
byte[] secretKey = key.getBytes();
byte[] digestSeed = mDigest.digest(secretKey);
byte[] hashKey = Arrays.copyOf(digestSeed, 16);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec skspec = new SecretKeySpec(hashKey, "AES");
String cipherKey = new String(secretKey);
GCMParameterSpec gcmParams = new GCMParameterSpec(128, cipherKey.substring(0, 16).getBytes());
cipher.init(operation, skspec, gcmParams);
return cipher.doFinal(inputText);
}
public static void main(String[] args) {
try {
System.out.println(encrypt("Password", "1234567890123456"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
to C# .NET 5.0 using the new AesGcm class:
using System;
using System.Security.Cryptography;
using System.Text;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
string inputText = "Password";
string msgId = "1234567890123456";
byte[] hashKey;
byte[] secretKey = Encoding.ASCII.GetBytes(msgId);
using (var hasher = SHA512.Create())
{
byte[] digestSeed = hasher.ComputeHash(secretKey);
hashKey = new byte[16];
Array.Copy(digestSeed, hashKey, hashKey.Length);
}
using (var aesGcm = new AesGcm(hashKey))
{
byte[] nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
byte[] plainText = Encoding.ASCII.GetBytes(inputText);
byte[] authTag = new byte[AesGcm.TagByteSizes.MaxSize];
byte[] cipherText = new byte[plainText.Length];
aesGcm.Encrypt(nonce, plainText, cipherText, authTag);
string cipherTextBase64 = Convert.ToBase64String(cipherText);
string authTagBase64 = Convert.ToBase64String(authTag);
Console.WriteLine(cipherTextBase64);
Console.WriteLine(authTagBase64);
}
}
}
}
But I don't know what the nonce is supposed to be. Not seeing that in the java code anywhere. Can anyone give me any pointers to this?
The result of the java code is: "gc1zTHlIPQusN5e+Rjq+veDoIYdU1nCQ"
mine is obviously incomplete and not coming close.
IV and Nonce mean the same thing.
The IV is the second argument to GCMParameterSpec here:
GCMParameterSpec gcmParams = new GCMParameterSpec(128, cipherKey.substring(0, 16).getBytes());
.NET calls this Nonce.
I was able to use BouncyCastle to convert this to C#:
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Security.Cryptography;
using System.Text;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
string inputText = "Password";
string msgId = "1234567890123456";
string value = Encrypt(inputText, msgId);
Console.WriteLine(value);
}
public static string Encrypt(string plainText, string msgId)
{
const byte GcmTagSize = 16;
byte[] hashKey;
byte[] secretKey = Encoding.ASCII.GetBytes(msgId);
using (var hasher = SHA512.Create())
{
byte[] digestSeed = hasher.ComputeHash(secretKey);
hashKey = new byte[16];
Array.Copy(digestSeed, hashKey, hashKey.Length);
}
var keyParameter = new KeyParameter(hashKey);
var keyParameters = new AeadParameters(keyParameter, GcmTagSize * 8, secretKey);
var cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding");
cipher.Init(true, keyParameters);
var plainTextData = Encoding.ASCII.GetBytes(plainText);
var cipherText = cipher.DoFinal(plainTextData);
return Convert.ToBase64String(cipherText);
}
}
}
I am currently using Cipher cipher = Cipher.getInstance ("AES / CBC / PKCS5Padding") on my Android app.
Those responsible for the security of the app tell me this: "It should also be noted that AES encryption is secure when it is not AES CBC.", so they want me to modify the algorithm.
I tried AES/GCM/NoPadding and AES/CTR/PKCS5Padding, if I uninstall the old version and install it again, the app works, but if I install it on top of a version with CBC I get the following error: javax.crypto.BadPaddingException: pad block corrupted
How can I solve this? I am afraid that if I update the app that is in the store, this error will happen to end users.
Notes:
public static String encrypt (String plaintext, String pwd) {
try {
byte [] salt = generateSalt ();
SecretKey key = deriveKey (salt, pwd);
Cipher cipher = Cipher.getInstance (CIPHER_ALGORITHM);
byte [] iv = generateIv (cipher.getBlockSize ());
IvParameterSpec ivParams = new IvParameterSpec (iv);
cipher.init (Cipher.ENCRYPT_MODE, key, ivParams);
byte [] cipherText = cipher.doFinal (plaintext.getBytes ("UTF-8"));
if (salt! = null) {
return String.format ("% s% s% s% s% s", toBase64 (salt), DELIMITER,
toBase64 (iv), DELIMITER, toBase64 (cipherText));
}
return String.format ("% s% s% s", toBase64 (iv), DELIMITER,
toBase64 (cipherText));
} catch (GeneralSecurityException e) {
throw new RuntimeException (e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException (e);
}
}
public static String decrypt (byte [] cipherBytes, SecretKey key, byte [] iv) {
try {
Cipher cipher = Cipher.getInstance (CIPHER_ALGORITHM);
IvParameterSpec ivParams = new IvParameterSpec (iv);
cipher.init (Cipher.DECRYPT_MODE, key, ivParams);
byte [] plaintext = cipher.doFinal (cipherBytes);
String plainrStr = new String (plaintext, "UTF-8");
return plainrStr;
} catch (GeneralSecurityException e) {
throw new RuntimeException (e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException (e);
}
}
etc...
Update!
I decided to make the code cleaner and here it is for you to understand. My goal was to replace "AES / CBC / PKCS7Padding" with "AES / GCM / NoPadding", as they consider AES with CBC unsafe :(
Questions that arose for this GCM implementation: do I have to use GCMParameterSpec on the cipher? Do I need to import the BouncyCastle provider?
public static final String PBKDF2_DERIVATION_ALGORITHM = "PBKDF2WithHmacSHA1";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
//private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
private static String DELIMITER = "]";
private static final int PKCS5_SALT_LENGTH = 8;
private static SecureRandom random = new SecureRandom();
private static final int ITERATION_COUNT = 1000;
private static final int KEY_LENGTH = 256;
public static String encrypt(String plaintext, String pwd) {
byte[] salt = generateSalt();
SecretKey key = deriveKey(pwd, salt);
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
byte[] iv = generateIv(cipher.getBlockSize());
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));
return String.format("%s%s%s%s%s", toBase64(salt), DELIMITER, toBase64(iv), DELIMITER, toBase64(cipherText));
} catch (GeneralSecurityException | UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static String decrypt(String ciphertext, String pwd) {
String[] fields = ciphertext.split(DELIMITER);
if (fields.length != 3) {
throw new IllegalArgumentException("Invalid encypted text format");
}
byte[] salt = fromBase64(fields[0]);
byte[] iv = fromBase64(fields[1]);
byte[] cipherBytes = fromBase64(fields[2]);
SecretKey key = deriveKey(pwd, salt);
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivParams);
byte[] plaintext = cipher.doFinal(cipherBytes);
return new String(plaintext, "UTF-8");
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private static byte[] generateSalt() {
byte[] b = new byte[PKCS5_SALT_LENGTH];
random.nextBytes(b);
return b;
}
private static byte[] generateIv(int length) {
byte[] b = new byte[length];
random.nextBytes(b);
return b;
}
private static SecretKey deriveKey(String pwd, byte[] salt) {
try {
KeySpec keySpec = new PBEKeySpec(pwd.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(PBKDF2_DERIVATION_ALGORITHM);
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
return new SecretKeySpec(keyBytes, "AES");
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
private static String toBase64(byte[] bytes) {
return Base64.encodeToString(bytes, Base64.NO_WRAP);
}
public static byte[] fromBase64(String base64) {
return Base64.decode(base64, Base64.NO_WRAP);
}
I have some code in Java that successfully verifies and sign messages with SHA256withRSA. However when I try to verify the same data with my c# code, I get a different signature and verification of the signature fails. As the SHA values match, i figure it not related to codepage. I tried multiple ways to figure this one out, but is yet to fail, so any ideas is more than welcome.
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.X509EncodedKeySpec;
import java.io.*;
import java.util.*;
import java.security.*;
import java.util.Base64;
import java.lang.*;
import java.nio.charset.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMException;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
public class Main {
public static void main(String[] args) throws Exception {
String privatePem = "c:\\Lab\\Cert\\private.pem";
String publicPem = "C:\\Lab\\Cert\\public.pem";
String datafile = "C:\\Lab\\Cert\\data.txt";
byte[] buf = Files.readAllBytes(Paths.get(datafile));
String message = new String(buf, StandardCharsets.UTF_8);
System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------");
System.out.println("Message to sign:");
System.out.println(message);
System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------");
PrivateKey privateKey = PrivateKeyReader(privatePem).getPrivate();
PublicKey publicKey = get(publicPem);
// Get SHA-256
byte[] messageAsByte = message.getBytes(Charset.forName( "UTF-8" ));
byte[] sha256OfMessage = digestSha256(messageAsByte);
byte[] sha512OfMessage = digestSha512(messageAsByte);
byte[] base64encodedSha256 = Base64.getEncoder().encode(sha256OfMessage);
byte[] base64encodedSha512 = Base64.getEncoder().encode(sha512OfMessage);
String Sha256ContentDigest = new String(base64encodedSha256, StandardCharsets.UTF_8);
String Sha512ContentDigest = new String(base64encodedSha512, StandardCharsets.UTF_8);
byte[] signature256 = generateSignature256(messageAsByte, privateKey);
String sig25664 = Base64.getEncoder().encodeToString(signature256);
System.out.println("X-Content-Digest: SHA256 " + Sha256ContentDigest);
System.out.println("X-Signature: RSA-SHA256 " + sig25664);
System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------");
byte[] signature512 = generateSignature512(messageAsByte, privateKey);
String sig51264 = Base64.getEncoder().encodeToString(signature512);
System.out.println("X-Content-Digest: SHA512 " + Sha512ContentDigest);
System.out.println("X-Signature: RSA-SHA512 " + sig51264);
System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------");
System.out.println("Signature verification SHA256: " + verifySignature256(messageAsByte, sha256OfMessage, signature256, publicKey));
System.out.println("Signature verification SHA512: " + verifySignature512(messageAsByte, sha512OfMessage, signature512, publicKey));
System.out.println("-----------------------------------------------------------------------------------------------------------------------------------------");
}
private static KeyPair PrivateKeyReader(String keyPath) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(keyPath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Security.addProvider(new BouncyCastleProvider());
PEMParser pp = new PEMParser(br);
PEMKeyPair pemKeyPair = null;
try {
pemKeyPair = (PEMKeyPair) pp.readObject();
} catch (IOException e) {
e.printStackTrace();
}
try {
KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
return kp;
} catch (PEMException e) {
e.printStackTrace();
}
try {
pp.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static byte[] generateSignature256(byte[] requestMessage, PrivateKey privateKey) throws Exception {
byte[] contentDigest = digestSha256(requestMessage);
Signature signature = Signature.getInstance("Sha256withRSA");
signature.initSign(privateKey);
signature.update(contentDigest);
return signature.sign();
}
public static byte[] generateSignature512(byte[] requestMessage, PrivateKey privateKey) throws Exception {
byte[] contentDigest = digestSha512(requestMessage);
Signature signature = Signature.getInstance("Sha512withRSA");
signature.initSign(privateKey);
signature.update(contentDigest);
return signature.sign();
}
public static boolean verifySignature256(byte[] requestMessage, byte[] requestContentDigest, byte[] requestSignature, PublicKey publicKey) throws Exception {
byte[] contentDigest = digestSha256(requestMessage);
if (!Arrays.equals(requestContentDigest, contentDigest)) {
return false;
}
Signature signature = Signature.getInstance("Sha256withRSA");
signature.initVerify(publicKey);
signature.update(contentDigest);
return signature.verify(requestSignature);
}
public static boolean verifySignature512(byte[] requestMessage, byte[] requestContentDigest, byte[] requestSignature, PublicKey publicKey) throws Exception {
byte[] contentDigest = digestSha512(requestMessage);
if (!Arrays.equals(requestContentDigest, contentDigest)) {
return false;
}
Signature signature = Signature.getInstance("Sha512withRSA");
signature.initVerify(publicKey);
signature.update(contentDigest);
return signature.verify(requestSignature);
}
public static byte[] digestSha256(byte[] requestMessage){
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
return digest.digest(requestMessage);
} catch (Exception e){
return null;
}
}
public static byte[] digestSha512(byte[] requestMessage){
try {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
return digest.digest(requestMessage);
} catch (Exception e){
return null;
}
}
public static PublicKey get(String keyPath)
throws Exception {
Reader reader = new FileReader(keyPath);
PublicKey key;
try {
org.bouncycastle.util.io.pem.PemObject spki = new org.bouncycastle.util.io.pem.PemReader(reader).readPemObject();
key = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(spki.getContent()));
} catch (Exception ex) {
FileInputStream fin = new FileInputStream(keyPath);
CertificateFactory f = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)f.generateCertificate(fin);
key = certificate.getPublicKey();
}
return key;
}
}
Output:
-----------------------------------------------------------------------------------------------------------------------------------------
Message to sign:
abc123
-----------------------------------------------------------------------------------------------------------------------------------------
X-Content-Digest: SHA256 bKE9UspwyIPg8LsQHkJaiehiTeUdstI5JZOvaoQRgJA=
X-Signature: RSA-SHA256 H9DF4NYV9YOZ3B3iogDIdlTzzQpKGWniQNHF5ZxladLes0MDcFopUSzyO6XiO1Y/AVBGLK18iq2nCc8ho+fXb6c4V08/PSE4lrGJu7z8dAs9UwodDgAx3+TXBV8iNkGtj3XThy7QhvruPA0txRLgdaRmKSJsBSoR7HK6LC0ES2LYzypQFXuQ+4LInWETPc4Ttp9bgSf/h07bZaQMlbO29hIQXZc31WCVTGmsJOG+TMBdF+CpWF04sj12ThR539VCpGrJRrE6xsYSg2VQMgo9t2XkcC/nn3Z4FOMD4o5yuwjHHJO1Hs4wyZfpSehIT96pYwvhkyMM5fS0Ms/Po9WUUg==
-----------------------------------------------------------------------------------------------------------------------------------------
X-Content-Digest: SHA512 xwtd2ev7b1HQnUEytxcMnSB1CnhS8AaA9lZY8DEOgQBW5nY8NMmgCw6UAHb1RJXBafwjAszrMSA5JxxDRpUH3A==
X-Signature: RSA-SHA512 UT0UlWI06+pYg+OuJGCaoIua23lq/k3yATkO9wQOl7BGLO56t7dvVZQz8UYtzIUhTrDktw9McqyTncDH8bZKMNMMCPLR7K3xAe3gCgipYE8VSP8uVeLDlqKhc/4OO+HDL6T6L44L1dwy5jKBVbVxDDKib7b0lLtTUtTHIh9WOX74hF6P3OiAZ8CD7tJg4QjngJ0GcM9WKXzfDNxVnOzGkhSarhCu3vsUP7QwG2um54uaADgqcJoJvVVyhlwOPF4kPH8SaAPItUIbz46h4bpF182YFZ7QJeg8TmsqXeOdO2MPdKOPYQsPfwZVs/UFkl7Z0oC5WE9UX7Ds9B7/VkOudw==
-----------------------------------------------------------------------------------------------------------------------------------------
Signature verification SHA256: true
Signature verification SHA512: true
-----------------------------------------------------------------------------------------------------------------------------------------
.Net C# code attempt:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace VAS
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------");
byte[] messageAsByte = File.ReadAllBytes(#"C:\Lab\Cert\data.txt");
Console.WriteLine("Message to sign:");
Console.WriteLine(Encoding.UTF8.GetString(messageAsByte));
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------");
var publicKey = LoadPublicKey(#"C:\Lab\Cert\public.pem");
var privateKey = LoadPrivateKey(#"C:\Lab\Cert\private.pem");
var sha256OfMessage = digestSha256(messageAsByte);
var sha512OfMessage = digestSha512(messageAsByte);
string Sha256ContentDigest = Convert.ToBase64String(sha256OfMessage);
string Sha512ContentDigest = Convert.ToBase64String(sha512OfMessage);
HashAlgorithm hash256Algorith = SHA256Managed.Create();
HashAlgorithm hash512Algorith = SHA256Managed.Create();
byte[] sig256 = privateKey.SignData(messageAsByte, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
byte[] sig512 = privateKey.SignData(messageAsByte, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
var sig64256 = Convert.ToBase64String(sig256);
var sig64512 = Convert.ToBase64String(sig512);
Console.WriteLine("X-Content-Digest: SHA256 " + Sha256ContentDigest);
Console.WriteLine("X-Signature: RSA-SHA256 " + sig64256);
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------");
Console.WriteLine("X-Content-Digest: SHA512 " + Sha512ContentDigest);
Console.WriteLine("X-Signature: RSA-SHA512 " + sig64512);
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------");
var verify256 = publicKey.VerifyData(messageAsByte, CryptoConfig.MapNameToOID("SHA256"), sig256);
var verify512 = publicKey.VerifyData(messageAsByte, CryptoConfig.MapNameToOID("SHA512"), sig512);
Console.WriteLine("Signature verify 256: " + verify256);
Console.WriteLine("Signature verify 512: " + verify512);
Console.ReadKey();
}
public static RSACryptoServiceProvider LoadPublicKey(String path)
{
System.IO.StreamReader fileStream = File.OpenText(path);
PemReader pemReader = new PemReader(fileStream);
AsymmetricKeyParameter KeyParameter = (AsymmetricKeyParameter)pemReader.ReadObject();
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)KeyParameter);
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams);
csp.ImportParameters(rsaParams);
return csp;
}
public static RSACryptoServiceProvider LoadPrivateKey(String path)
{
System.IO.StreamReader fileStream = File.OpenText(path);
PemReader pemReader = new PemReader(fileStream);
AsymmetricCipherKeyPair KeyParameter = (AsymmetricCipherKeyPair)pemReader.ReadObject();
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyParameter.Private);
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams);
csp.ImportParameters(rsaParams);
return csp;
}
public static byte[] digestSha256(byte[] requestMessage)
{
SHA256Managed shHash = new SHA256Managed();
return shHash.ComputeHash(requestMessage);
}
public static byte[] digestSha512(byte[] requestMessage)
{
SHA512Managed shHash = new SHA512Managed();
return shHash.ComputeHash(requestMessage);
}
}
}
Output:
-----------------------------------------------------------------------------------------------------------------------------------------
Message to sign:
abc123
-----------------------------------------------------------------------------------------------------------------------------------------
X-Content-Digest: SHA256 bKE9UspwyIPg8LsQHkJaiehiTeUdstI5JZOvaoQRgJA=
X-Signature: RSA-SHA256 Wo0dFOfzAJJZTb4zpOHkPVdpgWS1K2Q5IdAAD1wQ+w1veAIbmu+XByBHAbme0PiazdqF6QokFm9IudF7NmyqNjNybIKSuTRPUiP474/kliQl7lDiJJoFejBIaVwQhHdds0CkomZZPulZZSYuIi7cqODaKCXxe/Js9tm/htMu3Wd6nejgaoMX3TGXHWyE6ixJI8Zq7ysD6yjksIWlYthsd0WmCR6mVTKR9zo7BiVPxYsOcJ7MFLSvyJgHHoFmXG9KBZhcA1rx8RquvWLGKxU+WWbt7u/9OqY+HKGPCPo2/S1xmdTP2kiVp1zhQ0JQ4uBgP9nkNqrBxh3QzSZgsCbJKg==
-----------------------------------------------------------------------------------------------------------------------------------------
X-Content-Digest: SHA512 xwtd2ev7b1HQnUEytxcMnSB1CnhS8AaA9lZY8DEOgQBW5nY8NMmgCw6UAHb1RJXBafwjAszrMSA5JxxDRpUH3A==
X-Signature: RSA-SHA512 V47yMVpBunwkUVz0lmi5ZJkYkj2+C9V3YX1MB7OaDvobCGc9F0vBoEsxsV0sDIR2gZsHVMowXFU2bHzIoNdeGz+iyichQ89fJXYP+qPQUZO42t0UXfefX/9LlMbkGlzOqFvfBkcOFidhF9x36ZGPcC6C9AjOC7r1sqL/IBxNENuknhcbBMzHHpJZXFzVo09U/p7LIs3kJxAE9TLkR4ir2syAfisKrbJYCTSZnwm38ikR35mMmigme8eByE6GuOmizshv7lrtd4K5d0RA1jWM1TrNKpLqil4IWbrYQXZCBnHUmLH4fTD7aGIpM+SxQXLBV/lDhWA3O8vXDdFnW0llxQ==
-----------------------------------------------------------------------------------------------------------------------------------------
Signature verify 256: True
Signature verify 512: True
Testkeys and data
private.pem:
-----BEGIN RSA PRIVATE KEY-----
MIIEoQIBAAKCAQBk04fDxgG0eV/b7wcTYK7kq72w4YMzlPyBy6hERHWD2DhuM6TQ
MF7cafxc4b8krGMBqgV9m7AQxhWn4GCmCHljacXivTc1qBp3S54IitZFqvyGhnC0
dqKshqaL6z/S1kbiPZmiiXpZScYkje5pxY7k11PTopqnV9/g89Cu+PDEd7KcA0XE
XbYaEZtufvahZBmbF5mQPAr5YwGDgrR16CiAGi3dcWqX7g7AJb6bSJQp1SEWYVHU
klSdOtIJPgTDB57VIC8klKJ0c2Lnn3M+qPl6aD0qLTyl2QH1q97G+7E0e2dYAAbX
j0uU8753iEE/nHeOz09ACkIdLw9e97Kmka4DAgMBAAECggEAV9DE1oaGxaFRFEVD
bGUw7omGVaCUnUCODJ5Ml+joUUTpIVJpocn/VQoaeutDh7V9Jd3nmlcXKgTcp7KN
ew62axec+rbCd0FKi8yYf+gsZ9Fcz+4YC5WoaYt9UzA6DnACnNn6Dc6feVT/9qaH
mCgxJK9Gm3VsLYQjwdGZWEwJp5NhBXDHMAPIKJqGfI6v3XI3DOa/VPy4zCMrwMpb
Pps0NOMXiwOmWlDVZsDdc36/oICHpib3qHH9Crgbo4i3hDiCCnC97fJiZW6FjfiJ
TtXAIPDAfMIW/etLD6lI9O0s3IbcRf4GjnkmM/JMaJnV9mqqN4Nrn57uDyUC5Ged
2/v6gQKBgQCpWGSe16bFYZQsZunJAcdRGqoj0o3dCb3HpB1pnnKdahIsBYguLlnm
y2QaVXuFPOUMkRfrOGDITP4hSUiN0hsFT1uThE5IsT4u2KdUe2kSlgWerihPWfuZ
UO5w0ag3mgv4avUlg9/wAlRbq7L9s+QivnNxsR6aSuyb+cqLWW8WuQKBgQCYa2bp
FTWO5MDRxia4rHvcj+/4bt7zFwX1JUwfbFR8VtUul/Wk5w2JnzEQgF+Td7gJJxv8
u4JJxZNh8TOqek58lyg1KQKSod8mp8CnW9A2utU2MapZsCxyY7T1jgmXVvcXCQ3W
eJs1VpgQnoZxbzqbV9muQWjQRCCSR/WQ6hBMmwKBgG7G8vNxkJe30E0HeVFTR4ZH
khri5og8khfhxJfN3Z4ZwA9qAv5qtcajMDWFy8qJ3i/NTj9B3xXIP8mYfczAL4rW
scobF3a38zyD31oFbOOKndyCgr391/cgGQpWK9tLex8jIIBM9xWzAGoDNJB/t/H+
cdhii+lUr9kMmzFy7JeJAoGABR3V3o0vtxRGxMP6GMjxf331eEmAgniLYqdV3tgs
HeBsV5wSSu7WrYACjaNBkhm6u9PsRJem0AMp52fJbDee2t/YIbC2vWVhsFKBTRzv
6GZtMdyI82nOlCh0sqmJ+OKaeNN8+24hB7FYeXZY3QX22bAhRpA7jII89awkujCh
S3ECgYBNdGKf5NXxL1n//7GlBsH8sIyNUnHN4dQOORPdSSsynqDcpbdkRFkBIioF
5Q70DOhyS69F8Yu4d1qr09E7AbFpMmQjieDwzdZ6z0b9WInbcKo71FqCaZzz8azt
AMG22E827GX9z7F207rPf7GWpvhpGjzbxHXGXSEyFy2CvetpAA==
-----END RSA PRIVATE KEY-----
public.pem:
-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBk04fDxgG0eV/b7wcTYK7k
q72w4YMzlPyBy6hERHWD2DhuM6TQMF7cafxc4b8krGMBqgV9m7AQxhWn4GCmCHlj
acXivTc1qBp3S54IitZFqvyGhnC0dqKshqaL6z/S1kbiPZmiiXpZScYkje5pxY7k
11PTopqnV9/g89Cu+PDEd7KcA0XEXbYaEZtufvahZBmbF5mQPAr5YwGDgrR16CiA
Gi3dcWqX7g7AJb6bSJQp1SEWYVHUklSdOtIJPgTDB57VIC8klKJ0c2Lnn3M+qPl6
aD0qLTyl2QH1q97G+7E0e2dYAAbXj0uU8753iEE/nHeOz09ACkIdLw9e97Kmka4D
AgMBAAE=
-----END PUBLIC KEY-----
data.txt:
abc123
I also tried signing with OpenSSL, and that gives the same result i get with C#. Any help would be appricated so I can handle the data that is generated in Java.
Thanks!
The difference is in handling the hash. In .NET you are handling it correctly:
byte[] sig256 = privateKey.SignData(messageAsByte, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
however in Java, for some reason, you are feeding a precomputed hash value instead of the data:
byte[] contentDigest = digestSha256(requestMessage);
...
signature.update(contentDigest);
In other words, your data is hashed, and then the hash over the data is hashed.
Remember that signature generation in general includes the hashing of the data. Sometimes you can feed a precomputed hash value into the signature generation / verification, but commonly you'll have to call a specifically named method for that, calls such as update are for the message data itself.
Both .NET and Java use PKCS#1 v1.5 padding in your code snippets. PKCS#1 v1.5 padding for signature generation is indeed deterministic and considered secure. PSS is a newer, non-deterministic and more secure method and should be preferred for new protocols & applications.
As a small bonus, here is some code for testing:
private static final String PUB_BASE_64 = "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBk04fDxgG0eV/b7wcTYK7k" +
"q72w4YMzlPyBy6hERHWD2DhuM6TQMF7cafxc4b8krGMBqgV9m7AQxhWn4GCmCHlj" +
"acXivTc1qBp3S54IitZFqvyGhnC0dqKshqaL6z/S1kbiPZmiiXpZScYkje5pxY7k" +
"11PTopqnV9/g89Cu+PDEd7KcA0XEXbYaEZtufvahZBmbF5mQPAr5YwGDgrR16CiA" +
"Gi3dcWqX7g7AJb6bSJQp1SEWYVHUklSdOtIJPgTDB57VIC8klKJ0c2Lnn3M+qPl6" +
"aD0qLTyl2QH1q97G+7E0e2dYAAbXj0uU8753iEE/nHeOz09ACkIdLw9e97Kmka4D" +
"AgMBAAE=";
private static final String SIG_SHA256_DOTNET_BASE_64 = "Wo0dFOfzAJJZTb4zpOHkPVdpgWS1K2Q5IdAAD1wQ+w1veAIbmu+XByBHAbme0PiazdqF6QokFm9IudF7NmyqNjNybIKSuTRPUiP474/kliQl7lDiJJoFejBIaVwQhHdds0CkomZZPulZZSYuIi7cqODaKCXxe/Js9tm/htMu3Wd6nejgaoMX3TGXHWyE6ixJI8Zq7ysD6yjksIWlYthsd0WmCR6mVTKR9zo7BiVPxYsOcJ7MFLSvyJgHHoFmXG9KBZhcA1rx8RquvWLGKxU+WWbt7u/9OqY+HKGPCPo2/S1xmdTP2kiVp1zhQ0JQ4uBgP9nkNqrBxh3QzSZgsCbJKg==";
private static final String SIG_SHA256_JAVA_BASE_64 = "H9DF4NYV9YOZ3B3iogDIdlTzzQpKGWniQNHF5ZxladLes0MDcFopUSzyO6XiO1Y/AVBGLK18iq2nCc8ho+fXb6c4V08/PSE4lrGJu7z8dAs9UwodDgAx3+TXBV8iNkGtj3XThy7QhvruPA0txRLgdaRmKSJsBSoR7HK6LC0ES2LYzypQFXuQ+4LInWETPc4Ttp9bgSf/h07bZaQMlbO29hIQXZc31WCVTGmsJOG+TMBdF+CpWF04sj12ThR539VCpGrJRrE6xsYSg2VQMgo9t2XkcC/nn3Z4FOMD4o5yuwjHHJO1Hs4wyZfpSehIT96pYwvhkyMM5fS0Ms/Po9WUUg==";
public static void main(String[] args) throws Exception {
KeyFactory rsaKeyFactory = KeyFactory.getInstance("RSA");
PublicKey pub = rsaKeyFactory.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(PUB_BASE_64)));
Cipher rsa = Cipher.getInstance("RSA/ECB/NoPadding");
rsa.init(Cipher.DECRYPT_MODE, pub);
{
byte[] sig = Base64.getDecoder().decode(SIG_SHA256_JAVA_BASE_64);
byte[] plainSigJava = rsa.doFinal(sig);
System.out.println(Hex.toHexString(plainSigJava));
}
{
byte[] sig = Base64.getDecoder().decode(SIG_SHA256_DOTNET_BASE_64);
byte[] plainSigDotNet = rsa.doFinal(sig);
System.out.println(Hex.toHexString(plainSigDotNet));
}
byte[] hashSha256 = Base64.getDecoder().decode("bKE9UspwyIPg8LsQHkJaiehiTeUdstI5JZOvaoQRgJA=");
System.out.println(Hex.toHexString(hashSha256));
}
prints:
0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420efaaeb3b1d1d85e8587ef0527ca43b9575ce8149ba1ee41583d3d19bd130daf8
0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090
6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090
Note that the last signature "decryption" is the .NET one and contains the right hash value, printed on the final line.
Sorry, I used a non-standard Hex decoder, the rest is plain Java that you can put in a class definition.
Im trying to decrypt the encrypted xml file. Im getting it as a inputstream as follows.I have the correct encrypt key. but each time my program returns empty string. Every time i enter the correct key. but each time it returns Badpadding Exception.
try{
InputStream is = new ByteArrayInputStream(decryption.getFileData().getBytes());
String xmlEncryptedStr = getStringFromInputStream(is);
String xmlStr = CipherUtils.decrypt(xmlEncryptedStr, new Long(key));
.......
here is my CipherUtils.java class
.........
public static String decrypt(String strToDecrypt,Long key)
{
String keyString=String.format("%016d", key);
//System.out.println("decrypt keyString :"+keyString);
return decrypt(strToDecrypt, keyString.getBytes());
}
public static String decrypt(String strToDecrypt,byte[] key)
{
if(strToDecrypt==null)
return strToDecrypt;
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
System.out.println("CipherUtils.decryptedString :"+decryptedString);
return decryptedString;
}
catch (Exception e)
{
log.error("Ops!", e);
}
return null;
}
.......
For more information here is my encrypting code
public static String encrypt(String strToEncrypt,Long key)
{
String keyString=String.format("%016d", key);
//System.out.println("encrypt keyString :"+keyString);
return encrypt(strToEncrypt,keyString.getBytes());
}
public static String encrypt(String strToEncrypt,byte[] key)
{
if(strToEncrypt==null)
return strToEncrypt;
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
// System.out.println("CipherUtils.encrypt :"+encryptedString);
return encryptedString;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
I am sorry I couldn't comment so I am writing in answers section.
I faced this issue when I was using different keys though I was passing the same but i used CBC methodology.
Just to note that have you checked that encryption is also done by the AES/ECB/PKCS5Padding and not other format like AES/CBC/PKCS5Padding
Also check if key format for encryption is also having the same format like %016d of your keyValue. Also the key is 16 char long.
I created a simple AES and DESede encryption utility and it worked fine.
private static final byte[] keyValue = new String(
"CjxI&S#V&#DSA_S0dA-SDSA$").getBytes();
public static void main(String[] args) throws Exception {
Client cli = new Client();
System.out.println(cli.encrypt("your password for encryption"));
Client cli1 = new Client();
System.out.println(cli1.decrypt("fTsgVQtXvv49GynHazT4OGZ4Va1H57d+6AM+44Ex040="));
}
public String encrypt(String Data) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = DatatypeConverter.printBase64Binary(encVal);
// String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public String decrypt(String encryptedData) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = DatatypeConverter
.parseBase64Binary(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
I am using the service like this
String value = "test#example.com"
String encrypedValue = EncrypterService get().encrypt(value.getBytes())
String decryptedValue = EncrypterService get().decrypt(encrypedValue .getBytes())
public final class EncrypterService {
private static Key keySpec;
private static Cipher encryptCipher;
private static Cipher decryptCipher;
private static String passphrase = "IU1ZaypiTiVYc3AtPXMxNWNMYGUmVUF8YUAtUSMuKVI=";
private static final String KEY_ALGORIGHT = "HmacSHA256";
private static final String CIPHER_ALGORITHM = "AES";
private static final String MD5_ALGORITH = "MD5";
private static EncrypterService service;
private EncrypterService(){
}
private static synchronized void initialize() {
if (service == null) {
service = new EncrypterService();
service.init();
}
}
public static EncrypterService get() {
initialize();
return service;
}
public String encrypt (byte[] plaintext){
//returns byte array encrypted with key
try {
byte[] encode = encryptCipher.doFinal(plaintext);
return new String(encode);
}catch(Exception e){
throw new RuntimeException("Unable to decrypt data" + e);
}
}
public String decrypt (byte[] ciphertext) {
//returns byte array decrypted with key
try {
byte[] decode = decryptCipher.doFinal(ciphertext);
return new String(decode);
}catch(Exception e){
throw new RuntimeException("Unable to decrypt data" + e);
}
}
private static void init(){
try {
if (encryptCipher == null && decryptCipher == null) {
byte[] bytesOfMessage = Base64.decode(passphrase, Base64.NO_WRAP);
MessageDigest md = MessageDigest.getInstance(MD5_ALGORITH);
byte[] thedigest = md.digest(bytesOfMessage);
keySpec = new SecretKeySpec(thedigest, KEY_ALGORIGHT);
encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM);
encryptCipher.init(Cipher.ENCRYPT_MODE, keySpec);
decryptCipher = Cipher.getInstance(CIPHER_ALGORITHM);
decryptCipher.init(Cipher.DECRYPT_MODE, keySpec);
}
}catch(Exception e){
throw new RuntimeException("Unable to initialise encryption", e);
}
}
}
stacktrace
java.lang.RuntimeException·Unable to decrypt datajavax.crypto.IllegalBlockSizeException: last block incomplete in decryption
Full TraceRaw
EncrypterService .java:59 EncrypterService .decrypt
Issue#1:
java.security.MessageDigest will provide an instance of MD5 digest.
For this, you need to import the following
import java.security.*;
Issue#2:
For encrypedValue, you are using value.getBytes() and
For decryptedValue , you are using encrypedValue .getBytes().
Here is some limitation for using getBytes(). It is platform independent.
so you should use getBytes("UTF-8") instead of getBytes()
byte[] bytesOfMessage = yourString.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance(MD5_ALGORITH);
byte[] thedigest = md.digest(bytesOfMessage);
Resource Link: How can I generate an MD5 hash?
Issue#3: Encoding and Decoding
Mr. Andrea suggested like below:
In Java 8, there is an officially supported API for Base64 encoding
and decoding
Sample code using the "basic" encoding:
import java.util.Base64;
byte[] bytes = "Hello, World!".getBytes("UTF-8");
String encoded = Base64.getEncoder().encodeToString(bytes);
byte[] decoded = Base64.getDecoder().decode(encoded);
Resource Link: Decode Base64 data in Java
return new String(encode);
The problem is here. String is not a container for binary data. The round trip between byte[] and String is not guaranteed. You should either just pass around the original byte[] or else hex- or base64-encode it.