Android проверить подпись файла с открытым ключом .der

Я пытаюсь проверить подпись файла. Я следовал этой инструкции, чтобы сгенерировать сертификат:

// generate a private key with size of 2048 bits
openssl genrsa -out private_key.pem 2048

// derive a public key from the above private key
openssl rsa -in private_key.pem -out public_key.pem -outform PEM -pubout

// iOS will not import PEM encoded data so it needs to be converted to DER encoded data
openssl rsa -pubin -inform PEM -outform DER -in public_key.pem -out public_key.der

// generate a self-signed certificate for testing
openssl req -new -x509 -key private_key.pem -out test_cert.pem -days 1095

// show the content of the original certificate
openssl x509 -in test_cert.pem -text -noout
// convert the certificate to DER format
openssl x509 -in test_cert.pem -outform der -out test_cert.der
// show the content of the new certificate
openssl x509 -in test_cert.der -inform der -text -noout

Я использовал пример наэта ссылка хэшировать некоторые данные и проверять, что все было хорошо (я сделал шаги 2 - 5).

Теперь я пытаюсь поместить файл .der, файл подписи и файл данных в приложение для Android и в основном убедиться, что все снова хорошо. Я не получаю никаких ошибок, но я не получаю ложные. Ниже приведен код, который я написал:

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.widget.TextView;

import java.io.*;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.Certificate;

// Most of the below is taken from:
// http://www.herongyang.com/JDK/Digital-Signature-JcaVerify-Signature-Verification-Program.html
public class MyActivity extends Activity {

String input = Environment.getExternalStorageDirectory() + "/data.txt";
String signFile = Environment.getExternalStorageDirectory() + "/signature";
String signAlgo = "SHA1withRSA";
int keyFile = R.raw.test_cert_josh;
String TAG = "VERIFY";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    TextView textView = (TextView) findViewById(R.id.textView);

    try {
        PublicKey pubKey = readPublicKey(keyFile);
        byte[] sign = readSignature(signFile);
        textView.setText(verify(input, signAlgo, sign, pubKey) + "");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

PublicKey readPublicKey(int cert_id) throws Exception {
    InputStream in = MyActivity.this.getResources().openRawResource(cert_id);
    byte[] buff = new byte[4000];
    int bytesRead;
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    while((bytesRead = in.read(buff)) != -1) {
        out.write(buff, 0, bytesRead);
        Log.i(TAG, "bytes read: " + bytesRead);
    }

    byte[] publicKeyBytes = out.toByteArray();

    CertificateFactory cf = CertificateFactory.getInstance("X509");
    Certificate cert = cf.generateCertificate(new ByteArrayInputStream(publicKeyBytes));

    PublicKey pubKey = cert.getPublicKey();
    Log.i(TAG, "Public Key Info: ");
    Log.i(TAG, "Algorithm = " + pubKey.getAlgorithm());
    Log.i(TAG, "toString = " + pubKey.toString());
    return pubKey;
}

byte[] readSignature(String input) throws Exception {
    FileInputStream signStream = new FileInputStream(input);
    byte[] signBytes = new byte[signStream.available()];
    signStream.read(signBytes);
    signStream.close();
    return  signBytes;
}

boolean verify(String input, String algorithm, byte[] sign, PublicKey pubKey) throws Exception {
    Signature sg = Signature.getInstance(algorithm);
    sg.initVerify(pubKey);
    Log.i(TAG, "Signature Object Info: ");
    Log.i(TAG, "Algorithm = "+sg.getAlgorithm());
    Log.i(TAG, "Provider = "+sg.getProvider());

    FileInputStream in = new FileInputStream(input);
    byte[] buff = new byte[in.available()];
    in.read(buff);

    sg.update(buff);

    boolean ok = sg.verify(sign);
    Log.i(TAG, "Verify Processing Info: ");
    Log.i(TAG, "Verification result = "+ok);
    return ok;
}
}

Все, что я прочитал, говорит, что мой код правильный. Я думаю, что часть получения открытого ключа правильна, потому что модуль совпадает с модулем в реальном файле .der.

Пожалуйста помоги!

РЕДАКТИРОВАТЬ: Я думаю, что это связано с тем, как я читаю файл подписи или файл данных. Я почти уверен, что я правильно понимаю все об открытом ключе, потому что я распечатал дополнительную информацию о нем, и он соответствует вывод openssl

РЕДАКТИРОВАТЬ согласно предложению Николая ниже, я попытался подписать те же данные внутри приложения Android, которые я подписывал в openssl, используя этот код:

// testing code to sign it myself
// read the data file in
FileInputStream dataStream = new FileInputStream(input);
byte[] dataBytes = new byte[dataStream.available()];
dataStream.read(dataBytes);
dataStream.close();

// hash the data file, like i do with openssl
// per Nikolay's comments, this is not needed
MessageDigest digest = MessageDigest.getInstance("SHA-1");
// digest.update(dataBytes, 0, dataBytes.length);
// dataBytes = digest.digest();
Log.i(TAG, "data from file: " + new String(dataBytes));

// read the private key in
FileInputStream fis = new FileInputStream(Environment.getExternalStorageDirectory() + "/phaero/private_key.pem");
byte[] keyBytes = new byte[fis.available()];
fis.read(keyBytes);
fis.close();

// clean up the private key and decode it
String temp = new String(keyBytes);
Log.i(TAG, "private key: " + temp);
String privKeyPEM = temp.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
byte[] decoded = Base64.decode(privKeyPEM.getBytes(), Base64.DEFAULT);

// create the private key object from the private key data
PKCS8EncodedKeySpec private_spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey =  kf.generatePrivate(private_spec);

// set up for signing
Signature signer = Signature.getInstance(signAlgo);
signer.initSign(privateKey);
signer.update(dataBytes, 0, dataBytes.length);

// sign, and hash again so i can compare against openssl output
byte[] signed = signer.sign();
digest.update(signed, 0, signed.length);
Log.i(TAG, new BigInteger(1, digest.digest()).toString(16));

Краткое примечание: используя приведенный выше код в Jelly Bean, вы должны указать «BC» при создании KeyFactory.

Затем я хэшировал результат подписи, чтобы посмотреть, будет ли он совпадать с хешем файла подписи, созданного с помощью openssl, и они не совпадают ... поэтому я не знаю, что это значит, но я знаю, что это что-то значит! Я предполагаю, что мне нужно указать какую-то дополнительную опцию при создании файла подписи в openssl?

РЕДАКТИРОВАТЬ:

согласно комментарию Николая ниже, я обновил свой тестовый код, чтобы он не подписывался, но хэш подписи, созданной в java, все еще не соответствует хэшу файла подписи, созданного с помощью openssl ... не знаю, что не так, Java, OpenSSL или я.