【问题标题】:Converting Nodejs or Java signature hashing function to PHP将 Nodejs 或 Java 签名哈希函数转换为 PHP
【发布时间】:2020-10-21 18:33:40
【问题描述】:

我正在尝试使用 PHP 中的私钥创建 PKI 签名。

以下是创建签名的规则

  1. 使用 SHA-2 算法生成签名基本字符串的哈希。

  2. 使用应用程序的私钥对哈希值进行签名。

  3. Base64 编码签名值。 注意:Base64 编码不应包含每 72 个字符的 CRLF(回车/换行) 这是严格的 Base64 编码的一部分。相反,整个 Base64 编码的字符串应该没有 换行符。

  4. 将字符串设置为签名参数的值。

Nodejs 代码示例:

var signature = crypto.createSign('RSA-SHA256')
                      .update(baseString)
                      .sign(signWith, 'base64');

Java 代码

String baseString = "Constructed base string";
Signature sig = Signature.getInstance("RSA-SHA256");
sig.initSign(privateKey); // Get private key from keystone
sig.update(baseString.getBytes());
byte[] signedData = sig.sign();
String finalStr = Base64.getEncoder().encodeToString(signedData);

我正在尝试将此代码转换为 PHP, 我的基本字符串是正确的。

// $data = "BaseString";
// $private_key_pem = openssl_pkey_get_private("file://".$path."privateKey.pem",'passphrase');
$hash = hash('sha256', $data);
$result = openssl_sign($hash, $signature, $private_key_pem,'RSA-SHA256');
$signature = base64_encode($signature);
            

这是正确的吗? 如果是,API 响应是“无效的 PKI 签名”

【问题讨论】:

    标签: java php node.js digital-signature pki


    【解决方案1】:

    我用 Java 和 PHP 设置了两个程序来比较输出 (signature = finalStr) 和 签名的验证。为了获得可比较的结果,我对 RSA 密钥进行了硬编码 在这两个程序中,所以代码看起来有点奇怪。

    为了获得更短的密钥字符串,我生成了不安全的 512 位 RSA 密钥 - 在生产环境中至少使用 2048 位密钥。

    如您所见,这两个程序生成相同的签名:

    finalStr: NEHC7o+mW34qoTNOwXRQIRfs80s/YhudzX0K4AGlFTeyyJcRhit9f03iw58Ww1Eo3zfkSrrz3411TZheVLHFnQ==
    

    两个程序都可以验证签名为true

    这是Java代码:

    import java.security.*;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Base64;
    
    public class MainSo {
        public static void main(String[] args) throws NoSuchAlgorithmException, SignatureException, InvalidKeyException, InvalidKeySpecException {
            System.out.println("https://stackoverflow.com/questions/62674669/converting-nodejs-or-java-signature-hashing-function-to-php");
    
            // keys are sample rsa 512 keys
            String privateKey1 = "-----BEGIN PRIVATE KEY-----\n" +
                    "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqg8Hlhxm7LfqASjF\n" +
                    "KMce91anr2ViG/K8GQmk0HPMiw3Lh6DrGDGmsw2jUczwQTyv07qDwWwf+vaEiTdk\n" +
                    "jd1JxQIDAQABAkAOGbTtU2mNUyqJ8hF28hu1MnAw8N0TqCrEgLIzvoZFOTqvxPqc\n" +
                    "VaCuUs4Fm/J5x8gWLycsRmbBMeecIzvjzXY5AiEAtoZ4WSplvJbEHjiKhW+dRICc\n" +
                    "tSTcGaTf0v4vdfQTiGsCIQDug9wLUZDiSttbz2QlA3QthFX+UIu8fE/A/lGEjXnC\n" +
                    "jwIgcejRyrPO8jcVBdc7e7MAbvPk2Je8VLS0irTfYbmFRykCIQDCFsbu5vbxTlzm\n" +
                    "fwNNI1xc1b1sb3rmbHox4EHRjZaxfQIgEr2r53jmSRlyQfueo4nLZJhTGXdaJN8Z\n" +
                    "yoWwFsFqsiA=\n" +
                    "-----END PRIVATE KEY-----";
            String publicKey1 = "-----BEGIN PUBLIC KEY-----\n" +
                    "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoPB5YcZuy36gEoxSjHHvdWp69lYhvy\n" +
                    "vBkJpNBzzIsNy4eg6xgxprMNo1HM8EE8r9O6g8FsH/r2hIk3ZI3dScUCAwEAAQ==\n" +
                    "-----END PUBLIC KEY-----";
            // rsa key generation
            // Remove markers and new line characters in private key
            String realPrivateKey = privateKey1.replaceAll("-----END PRIVATE KEY-----", "")
                    .replaceAll("-----BEGIN PRIVATE KEY-----", "")
                    .replaceAll("\n", "");
            byte[] priKey = Base64.getDecoder().decode(realPrivateKey);
            PKCS8EncodedKeySpec specPri = new PKCS8EncodedKeySpec(priKey);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = kf.generatePrivate(specPri);
            // Remove markers and new line characters in public key
            String realPublicKey = publicKey1.replaceAll("-----END PUBLIC KEY-----", "")
                    .replaceAll("-----BEGIN PUBLIC KEY-----", "")
                    .replaceAll("\n", "");
            byte[] pubKey = Base64.getDecoder().decode(realPublicKey);
            X509EncodedKeySpec specPub = new X509EncodedKeySpec(pubKey);
            PublicKey publicKey = kf.generatePublic(specPub);
    
            String baseString = "Constructed base string";
    
            //Signature sig = Signature.getInstance("RSA-SHA256");
            Signature sig = Signature.getInstance("SHA256withRSA");
            sig.initSign(privateKey); // Get private key from keystone
            sig.update(baseString.getBytes());
            byte[] signedData = sig.sign();
            String finalStr = Base64.getEncoder().encodeToString(signedData);
            System.out.println("finalStr: " + finalStr);
    
            // verify signature
            byte[] signedDataVerify = Base64.getDecoder().decode(finalStr);
            Signature sigVerify = Signature.getInstance("SHA256withRSA");
            sigVerify.initVerify(publicKey);
            sigVerify.update(baseString.getBytes());
            boolean verified = sigVerify.verify(signedDataVerify);
            System.out.println("signature verified: " + verified);
        }
    }
    

    这里是 PHP 代码:

    <?php
    // https://stackoverflow.com/questions/62674669/converting-nodejs-or-java-signature-hashing-function-to-php
    $data = 'Constructed base string';
    
    // sample 512 rsa keys
    $privateKey1 = "-----BEGIN PRIVATE KEY-----\n" .
            "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqg8Hlhxm7LfqASjF\n" .
            "KMce91anr2ViG/K8GQmk0HPMiw3Lh6DrGDGmsw2jUczwQTyv07qDwWwf+vaEiTdk\n" .
            "jd1JxQIDAQABAkAOGbTtU2mNUyqJ8hF28hu1MnAw8N0TqCrEgLIzvoZFOTqvxPqc\n" .
            "VaCuUs4Fm/J5x8gWLycsRmbBMeecIzvjzXY5AiEAtoZ4WSplvJbEHjiKhW+dRICc\n" .
            "tSTcGaTf0v4vdfQTiGsCIQDug9wLUZDiSttbz2QlA3QthFX+UIu8fE/A/lGEjXnC\n" .
            "jwIgcejRyrPO8jcVBdc7e7MAbvPk2Je8VLS0irTfYbmFRykCIQDCFsbu5vbxTlzm\n" .
            "fwNNI1xc1b1sb3rmbHox4EHRjZaxfQIgEr2r53jmSRlyQfueo4nLZJhTGXdaJN8Z\n" .
            "yoWwFsFqsiA=\n" .
            "-----END PRIVATE KEY-----\n";
    
    $publicKey1 = "-----BEGIN PUBLIC KEY-----\n" .
            "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoPB5YcZuy36gEoxSjHHvdWp69lYhvy\n" .
            "vBkJpNBzzIsNy4eg6xgxprMNo1HM8EE8r9O6g8FsH/r2hIk3ZI3dScUCAwEAAQ==\n" .
            "-----END PUBLIC KEY-----\n";
    
    $privateKey = openssl_pkey_get_private ($privateKey1);
    $publicKey = openssl_pkey_get_public($publicKey1);
    
    // create the signature
    openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA256);
    echo 'finalStr (Base64):' . PHP_EOL . base64_encode($signature) . PHP_EOL;
    
    // verify signature
    $result = openssl_verify($data, $signature, $publicKey, "sha256WithRSAEncryption");
    echo 'verified (0=false, 1=true): ' . $result;
    ?>
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 2019-05-23
    • 2020-12-09
    • 2012-10-29
    • 2012-06-20
    • 1970-01-01
    • 2021-08-26
    相关资源
    最近更新 更多