Android的验证文件的签名与.der公钥 [英] android verify signature of file with .der public key

查看:1672
本文介绍了Android的验证文件的签名与.der公钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想验证文件的签名。我按照这些指令可生成一个证书:

I'm trying to verify the signature of a file. I followed these instruction to generate a certificate:

// 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)。

I used the example at this link to hash some data and verify that everything was all good (I did steps 2 - 5).

现在我试图把.der文件,签名文件和数据文件到一个Android应用程序,基本上验证这一切都很好了。我没有得到任何错误,但我没有收到假的。下面是code我已经写了:

Now I'm trying to put the .der file, the signature file, and the data file into an Android application and basically verify it's all good again. I'm not getting any errors, but I'm not getting false.. Below is the code I've written:

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;
}
}

我读过的一切说我的code是正确的。我想获得公钥出来的部分是正确的,因为模量的一个在实际.der文件相匹配。

Everything I've read says my code is right. I think the part about getting the public key out is right because the modulus matches the one in the actual .der file.

请帮忙!

编辑: 我认为它做任何我如何读签名文件或数据文件中,我是pretty的肯定,我得到的一切公共密钥正确的,因为我打印出更多的信息关于它和它匹配到OpenSSL的输出

I think it has to do with either how I'm reading the signature file or data file in. I'm pretty sure I'm getting everything about the public key correctly because i printed out additional information about it and it matches up to the openssl output

修改 按照以下尼古拉的建议下,我试图签下了Android应用程序中使用这个code,我是登录的OpenSSL里面相同的数据:

EDIT per Nikolay's suggestion below, I tried to sign the same data inside of the Android app that I was signing in openssl using this code:

// 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));

快速注:使用上述code在果冻豆,你必须在创建的KeyFactory时指定BC

Quick note: using the above code in Jelly Bean, you have to specify "BC" when creating the KeyFactory.

然后我散列签名的结果,看它是否会匹配使用OpenSSL生成签名文件的哈希,他们不匹配..所以我不知道这意味着什么,但我知道这意味着什么!我假设我需要指定一些额外的选项OpenSSL中创建的签名文件时?

Then I hashed the signature result to see if it would match the hash of the signature file generated with openssl, and they don't match.. so i don't know what that means, but I know it means something! I'm assuming I need to specify some kind of additional option when creating the signature file in openssl?

编辑:

按照以下尼古拉的评论,我更新了我的测试code不签,但在Java中创建签名的哈希值仍犯规搭配使用OpenSSL创建签名文件的哈希......不知道什么是错的,爪哇,OpenSSL的,还是我。

per Nikolay's comment below, I updated my test code to not sign, but the hash of the signature created in java still doesnt match the hash of the signature file created with openssl... not sure what's wrong, Java, OpenSSL, or me.

推荐答案

在帮助从@NikolayElenkov了很多,我终于想通了,什么是错的。尝试不同的谷歌搜索,我偶然发现这个计算器的问题,那里的家伙说,有两种不同的签名命令,就可以运行。当我在创建所有我的签名,我是用的东西,我联系到上面的:

After A LOT of help from @NikolayElenkov, I finally figured out what was wrong. Trying a different google search, I stumbled upon this stackoverflow question, where the guy says there's two different signature commands you can run. When I was creating all my signature, I was using the stuff I linked to above:

// create a hash
echo 'data to sign' > data.txt
openssl dgst -sha1 < data.txt > hash
// sign it
openssl rsautl -sign -inkey private.pem -keyform PEM -in hash  > signature
// verify it
openssl rsautl -verify -inkey public.pem -keyform PEM -pubin -in signature > verified
diff -s verified hash

和从今天我发现后,我想:

and from the post I found today, I tried:

openssl dgst -sha1 -sign privateKey.pem -out signature1 someInputFile

其中,作为人说,创建一个不同的签名文件。这是我的Andr​​oid code所需要的一个!因此,得到的答案这个验证就是我需要改变我是如何生成我的签名档! (我就不会得到这个至今没有@NikolayElenkov,非常感谢!)

which, as the guy says, creates a different signature file. This is the one my Android code needed! So, the answer to get this to verify is I needed to change how I was generating my signature file! (I wouldn't have gotten this far without @NikolayElenkov, thanks a lot!)

这篇关于Android的验证文件的签名与.der公钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆