libsodium-jni icon indicating copy to clipboard operation
libsodium-jni copied to clipboard

crypto_sign_verify_detached() return -1 when keys are not generated in the same method

Open shaggi7 opened this issue 5 years ago • 5 comments

Hi, @joshjdevl I am making a encryption library using libsodium jni . This is my method

 public void test(){
        int ret=0;

        long publickeylen = Sodium.crypto_sign_publickeybytes();
        long privatekeylen = Sodium.crypto_sign_secretkeybytes();

        final byte[] public_key = new byte[(int)publickeylen];
        final byte[] private_key = new byte[(int)privatekeylen];

        Sodium.randombytes(public_key,(int)publickeylen);
        Sodium.randombytes(private_key,(int)privatekeylen);

        ret = Sodium.crypto_sign_keypair(public_key,private_key);
        long signatureLength = Sodium.crypto_sign_bytes();
        byte [] message = "test".getBytes();
        byte[] signatureBytes =  new byte[(int)signatureLength];
        final int[] signed_message_len = new int[1];
        final int[] message_len = new int[1];
        int ret2=Sodium.crypto_sign_detached(signatureBytes,signed_message_len,message,message.length,private_key);
        System.out.println("length of signature: "+signatureBytes.length);

        int message_len2 = 0 ;
        int isValid = Sodium.crypto_sign_verify_detached(signatureBytes, message, message.length, public_key);
        System.out.println("verification result in test: "+isValid);

    }

Although this method is verifying signature correctly but i am making seperate classes for PublicKeys, PrivateKey, Signature, KeyPair. And when i uses keys from these classess the verification always fails even i have manually verified that the keys are same at the time of creation, signing and verification. What can be the issue.

shaggi7 avatar Jan 17 '20 09:01 shaggi7

If you need to see code for this then here it is

  1. Keys.java
import org.libsodium.jni.Sodium;
import org.libsodium.jni.SodiumJNI;

public class Keys {

    PublicKey publicKey;
    PrivateKey privateKey;

    public Keys(){

        int ret=0;
        utils util = new utils();

        long publickeylen = Sodium.crypto_sign_publickeybytes();
        long privatekeylen = Sodium.crypto_sign_secretkeybytes();

        final byte[] public_key = new byte[(int)publickeylen];
        final byte[] private_key = new byte[(int)privatekeylen];

        Sodium.randombytes(public_key,(int)publickeylen);
        Sodium.randombytes(private_key,(int)privatekeylen);

        ret = Sodium.crypto_sign_keypair(public_key,private_key);

        byte[] epk = new byte[(int)publickeylen];
        byte[] esk = new byte[(int)privatekeylen];
        ret = SodiumJNI.crypto_sign_ed25519_pk_to_curve25519(public_key, epk);
        ret = SodiumJNI.crypto_sign_ed25519_sk_to_curve25519(private_key, esk);
        util.printByteArray("Public key while generation: ",public_key);
        util.printByteArray("Private key while generation: ",private_key);
        this.publicKey = new PublicKey(public_key, epk);
        this.privateKey = new PrivateKey(private_key, esk);
    }

    public PrivateKey getPrivateKey() {
        return this.privateKey;
    }

    public PublicKey getPublicKey() {
        return this.publicKey;
    }
}

  1. PublicKeys.java
import android.util.Base64;
import android.util.Log;

import com.protocol.tntproto.internals.Exceptions.InvalidLengthException;

import org.libsodium.jni.Sodium;
import org.libsodium.jni.SodiumJNI;

public class PublicKey {

    private static final String LOGTAG = "PUBLIC KEYS: ";
    private byte[] publicEdwardBytes = new byte[(int) Sodium.crypto_sign_publickeybytes()];
    private byte[] publicCurveBytes = new byte[(int) Sodium.crypto_sign_secretkeybytes()];
    public String publicEdward = null;
    public String publicCurve = null;

    public PublicKey(){
        Log.d(LOGTAG, "Empty public key");
    }

    public PublicKey(byte[] pk, byte[] epk){
        this.publicEdwardBytes = pk;
        this.publicCurveBytes = epk;
        this.encode();
    }

    public String getPublicEdward(){
        return this.publicEdward;
    }

    public String getPublicCurve(){
        return this.publicCurve;
    }

    private void encode(){
        this.publicEdward  = Base64.encodeToString(this.publicEdwardBytes,Base64.DEFAULT);
        this.publicCurve = Base64.encodeToString(this.publicCurveBytes, Base64.DEFAULT);
    }

    private void decode(){
        try {
            this.publicEdwardBytes = this.publicEdward.getBytes();
            this.publicCurveBytes = this.publicCurve.getBytes();
        }
        catch(NullPointerException e){
            System.out.print("public Key are null");
            throw e;
        }
    }

    public void verify(String messageString, Signature signature){
        System.out.println("Verifying your message!!!!!!!!!!!!!!!");
        try{
            byte [] message = messageString.getBytes();
            utils util = new utils();
            int len = message.length;
            final int[] message_len = new int[1] ;
            util.printByteArray("Public key while vrifying: ",this.publicEdwardBytes);
            util.printByteArray("Signature while verifying", signature.getSignatureBytes());
            int isValid = Sodium.crypto_sign_verify_detached(signature.getSignatureBytes(), message, message.length, this.publicEdwardBytes);
            System.out.println("verification result "+isValid);
        }
        catch(NullPointerException e){
            System.out.println(e.getMessage());
        }
    }

    public void test(){
        int ret=0;

        long publickeylen = Sodium.crypto_sign_publickeybytes();
        long privatekeylen = Sodium.crypto_sign_secretkeybytes();

        final byte[] public_key = new byte[(int)publickeylen];
        final byte[] private_key = new byte[(int)privatekeylen];

        Sodium.randombytes(public_key,(int)publickeylen);
        Sodium.randombytes(private_key,(int)privatekeylen);

        ret = Sodium.crypto_sign_keypair(public_key,private_key);
        long signatureLength = Sodium.crypto_sign_bytes();
        byte [] message = "test".getBytes();
        byte[] signatureBytes =  new byte[(int)signatureLength];
        final int[] signed_message_len = new int[1];
        final int[] message_len = new int[1];
        int ret2=Sodium.crypto_sign_detached(signatureBytes,signed_message_len,message,message.length,private_key);
        System.out.println("length of signature: "+signatureBytes.length);

        int message_len2 = 0 ;
        int isValid = Sodium.crypto_sign_verify_detached(signatureBytes, message, message.length, public_key);
        System.out.println("verification result in test: "+isValid);

    }
}

  1. PrivateKeys.java
package com.protocol.tntproto.internals;

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

import org.libsodium.jni.Sodium;

public class PrivateKey {

    private static final String LOGTAG = "PUBLIC KEYS: ";
    private byte[] privateEdwardBytes = new byte[(int) Sodium.crypto_sign_secretkeybytes()];
    private byte[] privateCurveBytes = new byte[(int) Sodium.crypto_sign_secretkeybytes()];
    public String privateEdward = null;
    public String privateCurve = null;

    public PrivateKey(){
        Log.d(LOGTAG,"Empty private key created");
    }

    public PrivateKey(byte[] sk,  byte[] esk){
        utils util = new utils();
        util.printByteArray("Private key while creating PrivateKey: ", sk);
        this.privateEdwardBytes = sk;
        this.privateCurveBytes = esk;
        this.encode();
    }

    public String getPrivateEdward(){
        return this.privateEdward;
    }

    public String getPrivateCurve(){
        return this.privateCurve;
    }

    public Signature sign(String message){
        byte[] messageBytes = message.getBytes();
        Signature sig = new Signature(this.privateEdwardBytes, messageBytes);
        utils util = new utils();
        util.printByteArray("Private key while vrifying: ",this.privateEdwardBytes);
        return sig;
    }

    private void encode(){
        this.privateEdward  = Base64.encodeToString(this.privateEdwardBytes,Base64.DEFAULT);
        this.privateCurve   = Base64.encodeToString(this.privateCurveBytes, Base64.DEFAULT);
    }

    private void decode(){
        try {
            this.privateEdwardBytes = this.privateEdward.getBytes();
            this.privateCurveBytes = this.privateCurve.getBytes();
        }
        catch(NullPointerException e){
            System.out.print("Private Keys are Null");
            throw e;
        }
    }

}

  1. Signature.java
import android.util.Base64;
import android.util.Log;

import org.libsodium.jni.NaCl;
import org.libsodium.jni.Sodium;
import org.libsodium.jni.SodiumJNI;

public class Signature {
    private static final String LOGTAG = "SIGNATURE: ";
    long signatureLength = Sodium.crypto_sign_bytes();
    byte[] signatureBytes =  new byte[(int)signatureLength];
    String signature = null;
//    public Signature()

    public String getSignature(){
        return this.signature;
    }

    public byte[] getSignatureBytes() {
        return this.signatureBytes;
    }

    public Signature(byte[] sk, byte[] message){

        final int[] signed_message_len = new int[1];
        final int[] message_len = new int[1];
        int ret=Sodium.crypto_sign_detached(this.signatureBytes,signed_message_len,message,message.length,sk);
        utils util = new utils();
        util.printByteArray("private byte while creating signature: ",sk);
        util.printByteArray("Signature created: ",this.signatureBytes);
        this.encode();
    }

    private void encode(){
        this.signature = Base64.encodeToString(this.signatureBytes,Base64.DEFAULT);
        return;
    }

    private void decode(){
        this.signatureBytes = this.signature.getBytes();
        return;
    }

}

shaggi7 avatar Jan 17 '20 09:01 shaggi7

Have you tried initialization?

import org.libsodium.jni.NaCl; (this calls System.loadLibrary("sodiumjni");) call NaCl.sodium().

https://github.com/joshjdevl/libsodium-jni#usage

https://github.com/joshjdevl/libsodium-jni/blob/master/src/test/java/org/libsodium/jni/publickey/SignatureTest.java

joshjdevl avatar Feb 09 '20 15:02 joshjdevl

Yes i have initialized NaCl.sodium() in the app start itself .

shaggi7 avatar Feb 10 '20 12:02 shaggi7

I have the same issue. It returns -1

I also tried sodium_crypto_sign_verify_detached() in PHP and that fails too. A signature generated in PHP works fine.

janekp avatar Feb 16 '20 15:02 janekp

Hello @joshjdevl , any update regarding this.

shaggi7 avatar Feb 24 '20 07:02 shaggi7