1

I'm trying to sign an encrypted message with a private key and verify it in Java. This is my first time working with encryption and signatures so I'm not sure how it is supposed to work and I'm kind of stuck here. The verification always returns false.

I am posting the code here with the most important parts included:

import android.util.Base64;
import android.util.Log;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

public class SignatureTest {

// testing signature
PublicKey javaPublicKey;
PrivateKey javaPrivateKey;

String message = "Hello world";


public void test() {

    try {
        GenerateKeys();
        byte[] messageBytes = message.getBytes("UTF-8");
        byte[] signature = rsaSign(messageBytes);
        boolean success = rsaVerify(messageBytes, signature);

        if(success){
            Log.e("yay", "yay");
        }
        else {
            Log.e("nay", "nay");
        }


    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

}

public void GenerateKeys() {

    SecureRandom random = null;
    try {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        random = SecureRandom.getInstance("SHA1PRNG");
        keyGen.initialize(1024, random);

        KeyPair pair = keyGen.generateKeyPair();

        javaPrivateKey = pair.getPrivate();
        javaPublicKey = pair.getPublic();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

public byte[] rsaSign (byte[] data) {

    byte[] cipherData = null;

    try {

        Signature s = Signature.getInstance("SHA1withRSA");
        s.initSign(javaPrivateKey);

        s.update(data);

        Log.e("s.sign()", Base64.encodeToString(s.sign(), Base64.DEFAULT));


        return s.sign();


    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (SignatureException e) {
        e.printStackTrace();
    }

    return cipherData;
}

public boolean rsaVerify (byte[] data, byte[] signature) {

    boolean success = false;

    try {

        Signature s = Signature.getInstance("SHA1withRSA");
        s.initVerify(javaPublicKey);

        s.update(data);

        success = s.verify(Base64.decode(signature, Base64.DEFAULT));

        if(success == true) {
            Log.i("yeay", "yay");
        }
        else {
            Log.i("nay", "nay");
        }

        return success;


    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (SignatureException e) {
        e.printStackTrace();
    }

    return false;
}
}

Can anyone tell me what I'm doing wrong here?

Evv
  • 178
  • 3
  • 8
  • At least tell me WHY you are downvoting this post – Evv May 20 '15 at 21:09
  • Be sure that your topic is not a duplicate and try to narrow down the area within your code that might be specific to the error. Stack is about asking *very* specific questions, not necessarily for general code review. I'm sure you have a good question buried in there, just dig it out! It's like a block of marble that just needs a little more removed... – Shrout1 May 20 '15 at 21:35
  • Thanks. I did narrow it down, but tried to make it possible to copy/paste the code and run it directly. The problem is that I don't know where the problem lies in the code. Any of the lines could be the problem. But thanks, I will do some more research. – Evv May 20 '15 at 21:39
  • Yep! Stack tends to be *very* critical, so be sure that you have done some homework before you post (not saying that you didn't!). Don't be discouraged however, the community is excellent for answers, you just have to be careful in how you approach it. Good luck! – Shrout1 May 20 '15 at 21:41
  • 1
    You are base64-decoding inside your verify function, but the signature was never base64-encoded in the first place. Also, you cannot repeatedly call Signature.sign() because the result is not cached inside the Signature object. You must call it once and save off the result yourself. – President James K. Polk May 21 '15 at 00:04

1 Answers1

3

In rsaSign method, do the following after line s.update(data);,

byte[] signature = s.sign();
Log.e("s.sign()", Base64.encodeToString(signature , Base64.DEFAULT));    
return signature;

Remember, A call to sign() method resets the signature object to the state it was in when previously initialized for signing via a call to initSign(PrivateKey). That is, the object is reset and available to generate another signature from the same signer, if desired, via new calls to update and sign.
Now, in the rsaVerify method, replace the line
success = s.verify(Base64.decode(signature, Base64.DEFAULT));
with,
success = s.verify(signature);

mazhar islam
  • 5,561
  • 3
  • 20
  • 41
  • Thank you! I think this was my problem. – Evv May 21 '15 at 09:56
  • @user3685322 If this solved your problem, consider [accepting](http://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256) it. When you reach 15 rep, you will be able to upvote posts. – Artjom B. May 23 '15 at 17:29