2
I receive an HTTP request that comes in the HEADER a signature (SHA1). I own, stored in a String, a private key. I need to generate the signature between the BODY of the HTTP request and my key and compare it to the signature that comes in the HEADER. I tried it this way:
public static boolean checkSignature(String body, String key, String assinatura) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, InvalidKeyException, SignatureException{
Signature sig = Signature.getInstance("SHA1withRSA");
PublicKey pkey;
byte encKey[] = key.getBytes();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
sig.initVerify(pubKey);
sig.update(body.getBytes());
return sig.verify(assinatura.getBytes());
}
However, error occurs in keyFactory.generatePublic (pubKeySpec). The java.security.spec.Invalidkeyspecexception: java.security.Invalidkeyexception: invalid key format is triggered. I have tried with Sha1withdsa as well. My key is in String. Do I need to turn it to some other format? How do I fix it? Thanks in advance.
Anderson
Please give more details as it is difficult to understand what is really happening. SHA-1 is a hash, not a digital signature (although a hash is usually the first step in a signature algorithm). Also, private keys are not used to verify signatures, they are used to sign (signature verification is done by public key). Finally, there is no point in "trying" RSA or DSA, you need to use the exact key format you have, and the exact signature algorithm employed. Please give more details of the protocol being used. Who signed what, and how?
– mgibsonbr
I’ll try to improve it. I get an HTTP request signed by a server. The signature comes in HEADER. I get it as a JAVA string. The signature is generated from my private key along with the BODY of the request. My private key is in a JAVA String as well. What I need is to play this signature in my application (because I also know the private key and BODY) to compare it to the signature sent by the server that sent me the HTTP request. If the signatures match, I’m sure my document was signed by the server.
– Anderson Cavalcanti
I’m not sure which algorithm is used! I don’t really understand the subject. However, the documentation from the server sending me the request says that the signature is SHA-1. The message comes something like sha1=3f547499cabz7876cfeed... representing the signature.
– Anderson Cavalcanti
That’s not how the public key digital signature works... You can sign the same data twice and exit two completely different signatures - and both valid! That’s because the signature algorithm is randomized. The only way I know how to verify a signature is by using the public key. However, from what you are saying, it is not a signature that is being sent, but a hash. This does not guarantee authenticity, it only helps integrity. I will try to write an answer explaining this.
– mgibsonbr
Ok mgibsonbr! I really appreciate the help!
– Anderson Cavalcanti
For reference only, the server documentation shows an example of how it was done in Ruby: def generated_signature 'sha1=' + Openssl::HMAC.hexdigest(Openssl::Digest.new('sha1'), secret_key, request_body)
 end;
– Anderson Cavalcanti
Now I understand what this is about. An HMAC is a type of signature, yes, but one that can only be verified by the person who signed it (since the verifier shares the same secret of the person who signs it). In this context, we do not use the term "private key", only "secret key" or even "key" to differentiate from asymmetric cryptography (where there is a pair of keys, a public and a private). See my answer, and pay close attention to the details, because any little mistake will make the signatures not match each other.
– mgibsonbr