How to validate a signature with a private key?

2

I get an HTTP request that comes in the HEADER a signature (SHA1). I have, 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 with the signature that comes in the HEADER. I tried it as follows:

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, an error occurs in keyFactory.generatePublic (pubKeySpec). The java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format exception is thrown. I have already tried with SHA1withDSA as well. My key is in String. Do I need to turn it to some other format? How do I solve this? Thank you in advance.

Anderson

    
asked by anonymous 13.11.2015 / 14:44

1 answer

0

There is a difference between signature via asymmetric cryptography (the one that uses public and private keys, usually called "digital signature") and signature via symmetric encryption. In this, a single secret value is used both for signing and for checking the signature. This "signature" in this context is often referred to as Message Authenticator Code ( Message Authentication Code - MAC), and is commonly implemented with the help of a # - Hashing-based Hash-Based Message Authentication Code. According to your last comment, this is what your server is using.

According to this question in SOen , a way to generate an HMAC (and consequently verify it, since in that case yes just compare the signatures) would be as follows:

public static boolean checkSignature(String body, String key, String assinatura) throws NoSuchAlgorithmException, InvalidKeyException {
    byte encKey[] = key.getBytes();
    SecretKeySpec keySpec = new SecretKeySpec(encKey, "HmacSHA1");

    Mac mac = Mac.getInstance("HmacSHA1");
    mac.init(keySpec);

    byte[] result = mac.doFinal(body.getBytes(CODIFICACAO_COMUM));

    // Compara o resultado com a assinatura, e retorna se são ou não iguais
}

Note: If your signature is encoded in hexadecimal, you must convert the result (variable result ) to a byte array to a hexadecimal string before comparing. Or the opposite, convert the string signature to array of bytes and then compare the arrays.

Attention: str.getBytes() is not the same thing that convert from / to hexadecimal, so be careful! In addition, getBytes uses the default encoding of the platform, which may not be the same on the client and server (eg, if your server is Linux and your client is Windows the text will be UTF-8 signed and verified in Cp1252 , and the results will not be the same).

    
17.11.2015 / 15:35