Bom dia amigos, tudo bem?
Sei que no fórum já possui outros tópicos do mesmo assunto, mas com nenhum deles consegui resolver meu problema. Com base nestes tópicos que eu consegui montar meu programinha. O meu caso é o seguinte, eu tenho um arquivo e neste arquivo tem seu conteúdo e a assinatura digital no rodapé, tenho também a chave pública para validar esta assinatura (não tenho acesso a chave privada, por isso o arquivo que me enviam já vem com a assinatura).
Até aí tudo bem, fiz meu programa, não ocorre nenhum erro aparente. Porém ao validar o conteúdo, o método de verificação da classe Signature, sempre me retorna falso. Já tentei fazer de outras maneiras (podem perceber que no código tem linhas comentadas), mas ainda não consegui resolver este caso. Meus conhecimentos em Java ainda são limitados, consegui entender o código obviamente, mas algumas coisas ainda não são claras para mim. Eu tenho esta mesma validação para .NET (como podem ver abaixo do código Java) e neste caso funciona.
Peço a ajuda de vocês, para saber onde estou errando no Java, ou o que falta para funcionar 100%.
Desde já agradeço.
PS.: coloquei o conteúdo do arquivo já em String para facilitar os tsstes.
Obrigado,
Rubens Dos Santos Filho
Java
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import sun.misc.BASE64Decoder;
@SuppressWarnings("restriction")
public class ValidFile {
private PublicKey publicKey;
private final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdqxkltzW8MIMRt3xreMcYR+qA" +
"XKXnTTZX6zoHH4gGUq0t1CueI5Ook5iZEn5pOYKLsMpnIStDso/51nzI9BULjiRJ" +
"0f/E7FMhaVekYS2m5B4+RaG4jrf+wZLJ1Koni3XgdOvpCa+bEMzGx5BYKtmFr7Oa" +
"bMnoj4qgw3IH7bDcUQIDAQAB";
private final String FILE_CHKSUM = "TT0fhJ0ihUJ8L0fEBkeke0Wh4CQpLQjj4vBroX4wh6tKfsdqcxYaEaj5d8+9rivI" +
"e7YA6wlfKtk3Kf2b31RYluYBMqvME/EQNUTWXvh4i1U8tpu7sP/akB2oWVlVMCNM" +
"2rFWIf/t/UtdG6uKHwZcZvleyTP35AU/HNdpEh3NhJ0=";
private final String FILE_CONTENT = "20120530\r\n053.113.791/0017-90 \r\n043.816.719/0001-08 ";
public static void main(String args[]) throws NoSuchAlgorithmException, IOException {
ValidFile vf = new ValidFile();
String chksum = vf.FILE_CHKSUM;
String content = vf.FILE_CONTENT;
byte[] data = null;
byte[] signature = null;
MessageDigest md = MessageDigest.getInstance("MD5");
data = md.digest(content.getBytes());
BASE64Decoder decode64 = new BASE64Decoder();
signature = decode64.decodeBuffer(chksum);
System.out.println("It's a valid data? (" + vf.validSignature(data, signature) + ").");
}
public ValidFile(){
/*
* The public key below "apparently" results the modulus and exponent
* to use in C#
*
* Modulus:
* 3asZJbc1vDCDEbd8a3jHGEfqgFyl5002V+s6Bx+IBlKtLdQrniOTqJOYmRJ+aTmC
* i7DKZyErQ7KP+dZ8yPQVC44kSdH/xOxTIWlXpGEtpuQePkWhuI63/sGSydSqJ4t1
* 4HTr6QmvmxDMxseQWCrZha+zmmzJ6I+KoMNyB+2w3FE=
*
* Exponent:
* AQAB
*
* -----BEGIN PUBLIC KEY-----
* MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdqxkltzW8MIMRt3xreMcYR+qA
* XKXnTTZX6zoHH4gGUq0t1CueI5Ook5iZEn5pOYKLsMpnIStDso/51nzI9BULjiRJ
* 0f/E7FMhaVekYS2m5B4+RaG4jrf+wZLJ1Koni3XgdOvpCa+bEMzGx5BYKtmFr7Oa
* bMnoj4qgw3IH7bDcUQIDAQAB
* -----END PUBLIC KEY-----
*
*/
}
private boolean loadPublicKey() {
BASE64Decoder decode64 = new BASE64Decoder();
try {
//Load the public key
byte[] pkBytes = decode64.decodeBuffer(this.PUBLIC_KEY);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
//EncodedKeySpec spec = new PKCS8EncodedKeySpec(pkBytes);
EncodedKeySpec spec = new X509EncodedKeySpec(pkBytes);
publicKey = keyFactory.generatePublic(spec);
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return true;
}
public boolean validSignature(byte[] data, byte[] signature) {
boolean status = true;
this.loadPublicKey();
try {
Signature sign = Signature.getInstance("MD5withRSA");
sign.initVerify(publicKey);
sign.update(data);
status = sign.verify(signature);
} catch (SignatureException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return status;
}
}
.NET
using System;
using System.Security.Cryptography;
using System.Text;
using System.Numerics;
namespace Teste
{
class Program
{
public static void Main()
{
try
{
string cChkSum = "TT0fhJ0ihUJ8L0fEBkeke0Wh4CQpLQjj4vBroX4wh6tKfsdqcxYaEaj5d8+9riv" +
"Ie7YA6wlfKtk3Kf2b31RYluYBMqvME/EQNUTWXvh4i1U8tpu7sP/akB2oWVlVMC" +
"NM2rFWIf/t/UtdG6uKHwZcZvleyTP35AU/HNdpEh3NhJ0=";
string cconteudo = "20120530\r\n053.113.791/0017-90 \r\n043.816.719/0001-08 ";
MD5 md5Hasher = MD5.Create();
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(cconteudo));
byte[] ChkSum = Convert.FromBase64String(cChkSum);
bool lValido = VerifyHash(data, ChkSum);
} catch (Exception e) {
Console.WriteLine("Error: {0}", e.Message);
}
}
public static bool VerifyHash(byte[] signedData, byte[] signature)
{
bool lret = false;
string xmlString = "<RSAKeyValue><Modulus>3asZJbc1vDCDEbd8a3jHGEfqgFyl5002V+s6Bx+IBlKtL" +
"dQrniOTqJOYmRJ+aTmCi7DKZyErQ7KP+dZ8yPQVC44kSdH/xOxTIWlXpGEtpuQePkWh" +
"uI63/sGSydSqJ4t14HTr6QmvmxDMxseQWCrZha+zmmzJ6I+KoMNyB+2w3FE=</Modul" +
"us><Exponent>AQAB</Exponent></RSAKeyValue>";
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSAPKCS1SignatureDeformatter RSADeformatter;
RSA.FromXmlString(xmlString);
RSADeformatter = new RSAPKCS1SignatureDeformatter(RSA);
RSADeformatter.SetHashAlgorithm("MD5");
lret = RSADeformatter.VerifySignature(signedData, signature);
return lret;
}
}
}