使用PHP openssl_verify()函数来验证Android客户端APP创建的签名和数据

时间:2013-05-04 02:37:48

标签: java php android openssl

我在openssl_verify()

上阅读了帖子

我想问一些与openssl_verify()有关的问题。

因为我的PHP代码无法验证从Java创建的签名...

对于服务器端,这是我的PHP代码

<?php
$data =$_POST['data'];
$signature=$_POST['sig'];
$pub_key=$_POST['pubkey'];

function print_input()
{
    global $data;
    global $signature;
    global $pub_key;
////////////////////////////////////////////////////////////////
// I output the public key to file, and check it to make sure they
// are in correct pem format.
///////////////////////////////////////////////////////////////
$f=fopen("./Personnel_Pubkey/pubkey.pem", "w");
fwrite($f,"$pub_key");
fclose($f);
$key = openssl_pkey_get_public ("./Personnel_Pubkey/pubkey.pem");

// doesn't work if you use PEM format public key, only works with X.509 format
// certificate, and cert and private key in PEM format.
$result=openssl_public_decrypt ( $signature, $data, $key);

////////////////////////////////////////////////////////////////
$sig=base64_decode($signature);

// for some reason, the value of $ok is always 0
$ok = openssl_verify($data, $sig, $key);

if ($ok == 1) {
    echo "good";
} 
elseif ($ok == 0) {
    echo "bad";} 
else {
    echo "ugly, error checking signature";
    }
}

print_input();

?>

对于客户端Android APP,这里是代码的相关部分:

// create public key and private key pair
keyGen = KeyPairGenerator.getInstance("DSA");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
keyGen.initialize(1024, random);

// Generate the Pair of Keys The final step is to generate the key pair 
// and to store the keys in PrivateKey  and PublicKey objects.
pair = keyGen.generateKeyPair();
priv = pair.getPrivate();
pub = pair.getPublic();

// Change to PEM format from original openssl format    
stringWriter = new StringWriter();
PEMWriter pemWriter = new PEMWriter(stringWriter);  
pemWriter.writeObject( pair.getPublic());
pemWriter.close();

// initialize  the signature
sig = Signature.getInstance("SHA1withDSA"); 
sig.initSign(priv);

// this is the original data     
String msg = "original msg";


OriginalMsgByteArray = msg.getBytes();

// put original data to signature
sig.update(OriginalMsgByteArray);

// sign the data, and get the byte array of signature 
byte[] realSig = sig.sign();

// change the binary to base64 format
signatureB = new String(Base64.encode(realSig));

基本上,我将{3}},msgsignatureB这三个参数上传到PHP服务器,但似乎无法正常工作....这里&#39;我的PEM文件内容:

stringWriter.toString()

2 个答案:

答案 0 :(得分:1)

我在上面的代码中看到了一些潜在的问题。

首先,根据PHP documentation,您希望在X509证书或私钥上使用openssl_get_publickey。公钥未列为选项。

其次,您希望将文件转换为变量,然后在openssl_get_publickey方法中使用该变量。见下文:

$fp = fopen("./cert.pem", "r");
$cert = fread($fp, 8192);
fclose($fp);
$key = openssl_get_publickey($cert);

第三,$ bsig未在任何地方声明或定义。

答案 1 :(得分:0)

到目前为止,我还没有找到解决方案来解决这个问题,但我找到了一种解决方法,而不是解决这个问题。如果您有相同的问题并且没有足够的时间来解决此问题,请参考this stackoverflow question link。它有RSA算法解决方案,其签名和公钥是从Android APP生成并与PHP验证。但是,如果有人向我提供了这个问题的解决方案,我将不胜感激。