Java服务器使用SHA256WithRSA签名消息,但是python无法验证

时间:2019-03-07 04:23:02

标签: java python rsa pycrypto

这是代码,第二个(消息,签名和公共密钥)在Java上可以正常工作,可以验证消息。但是当我使用python时,它将失败。 如果签名,则消息和代码将正确验证消息。 有人可以帮我检查一下问题吗?谢谢。

# -*- coding:utf-8 -*-
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5
from base64 import b64decode, b64encode

public_key = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALyJy3rlD9EtWqVBzSIYxRRuFWRVn3juht2nupDCBSsWi7uKaRu3W0gn5y6aCacArtCkrf0EehwYRm0A4iHf8rkCAwEAAQ=='
private_key = 'MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvInLeuUP0S1apUHNIhjFFG4VZFWfeO6G3ae6kMIFKxaLu4ppG7dbSCfnLpoJpwCu0KSt/QR6HBhGbQDiId/yuQIDAQABAkEAqm/y15UtOE7Ey/HxLCqyNqbRhdN1h5AxsT0IhgYvP+PhWGc3hRElMwNCdiNaJBh04R1iK6wmKoi3DSjkdU6IAQIhAPRL9khAdPMxjy5tpswNWeaDjNJrlUKEnItQUkoHqve5AiEAxZIDz235HcUgLg9ApYK4spOpzLDGCCgfO3FxmrUEUwECIEaLjQIOQvdbT1p75Ze1H0nWoRq+YGrF+qKsPicMkc1ZAiARlNTR+K9afthGQQU3tVJKUemiVXjJ8QgWehnp8oHYAQIhANsC2fEVjWv94Oy2c8I9qhuX+yfNtvZ2m+Kmf2o4JFrR'
bank_response_data = """{"head":{"vernbr":"1.0","mchnbr":"BILL0003","mchtyp":"BILLTYP","trscod":"BILL001","msgidc":"201805011230500001","sigtim":"20190307115511","sigalg":"SHA256WithRSA","retcod":"F","retmsg":"GWB2B006 源IP地址不在商户IP白名单中;商户编号:BILL0003;IP地址:123.139.40.150"}}"""
bank_response_signature = """uZl0/5D694GnAd/G9OPRs9BSd9fb0fZGXSGThBtgLnKi+CDQAdasOX05mKazXZki0blXxApGYRAWa/kOrf+Wl0USfklx0G5w/eGERfMdRWpvtV3S2MBCH/H/0T81nKGgn8svkT/Trj7+Mc+e654Jn8IijGyV9m8Ak92hG2bLtbc="""
bank_public_key = """MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZs4l8Ez3F4MG0kF7RRSL+pn8MmxVE3nfdXzjx6d3rH8IfDbNvNRLS0X0b5iJnPyFO8sbbUo1Im4zX0M8XA0xnnviGyn5E6occiyUXJRgokphWb5BwaYdVhnLldctdimHoJTk3NFEQFav3guygR54i3tymrDc8lWtuG8EczVu8FwIDAQAB"""

def sign():
    key_bytes = bytes(private_key, encoding="utf-8")
    key_bytes = b64decode(key_bytes)
    key = RSA.importKey(key_bytes)
    hash_value = SHA256.new(bytes(bank_response_data, encoding="utf-8"))
    signer = PKCS1_v1_5.new(key)
    signature = signer.sign(hash_value)
    return b64encode(signature)


def verify(data, signature, the_pub_key):
    print(signature)
    key_bytes = bytes(the_pub_key, encoding="utf-8")
    key_bytes = b64decode(key_bytes)
    key = RSA.importKey(key_bytes)
    hash_value = SHA256.new(bytes(data, encoding="utf-8"))
    verifier = PKCS1_v1_5.new(key)
    if verifier.verify(hash_value, b64decode(signature)):
        print("The signature is authentic.")
    else:
        print("The signature is not authentic.")


verify(bank_response_data, sign(), public_key)
verify(bank_response_data, bank_response_signature.encode('utf-8'), 
bank_public_key)

3 个答案:

答案 0 :(得分:0)

# -*- coding:utf-8 -*-
from Cryptodome.Signature import PKCS1_v1_5  # pip install pycryptodomex
from Cryptodome.Hash import SHA256
from Cryptodome.PublicKey import RSA
from base64 import decodebytes, encodebytes

public_key = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALyJy3rlD9EtWqVBzSIYxRRuFWRVn3juht2nupDCBSsWi7uKaRu3W0gn5y6aCacArtCkrf0EehwYRm0A4iHf8rkCAwEAAQ=="
private_key = "MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvInLeuUP0S1apUHNIhjFFG4VZFWfeO6G3ae6kMIFKxaLu4ppG7dbSCfnLpoJpwCu0KSt/QR6HBhGbQDiId/yuQIDAQABAkEAqm/y15UtOE7Ey/HxLCqyNqbRhdN1h5AxsT0IhgYvP+PhWGc3hRElMwNCdiNaJBh04R1iK6wmKoi3DSjkdU6IAQIhAPRL9khAdPMxjy5tpswNWeaDjNJrlUKEnItQUkoHqve5AiEAxZIDz235HcUgLg9ApYK4spOpzLDGCCgfO3FxmrUEUwECIEaLjQIOQvdbT1p75Ze1H0nWoRq+YGrF+qKsPicMkc1ZAiARlNTR+K9afthGQQU3tVJKUemiVXjJ8QgWehnp8oHYAQIhANsC2fEVjWv94Oy2c8I9qhuX+yfNtvZ2m+Kmf2o4JFrR"
bank_response_data = """{"head":{"vernbr":"1.0","mchnbr":"BILL0003","mchtyp":"BILLTYP","trscod":"BILL001","msgidc":"201805011230500001","sigtim":"20190307115511","sigalg":"SHA256WithRSA","retcod":"F","retmsg":"GWB2B006 源IP地址不在商户IP白名单中;商户编号:BILL0003;IP地址:123.139.40.150"}}"""
bank_response_signature = """uZl0/5D694GnAd/G9OPRs9BSd9fb0fZGXSGThBtgLnKi+CDQAdasOX05mKazXZki0blXxApGYRAWa/kOrf+Wl0USfklx0G5w/eGERfMdRWpvtV3S2MBCH/H/0T81nKGgn8svkT/Trj7+Mc+e654Jn8IijGyV9m8Ak92hG2bLtbc="""
bank_public_key = """MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZs4l8Ez3F4MG0kF7RRSL+pn8MmxVE3nfdXzjx6d3rH8IfDbNvNRLS0X0b5iJnPyFO8sbbUo1Im4zX0M8XA0xnnviGyn5E6occiyUXJRgokphWb5BwaYdVhnLldctdimHoJTk3NFEQFav3guygR54i3tymrDc8lWtuG8EczVu8FwIDAQAB"""


def sign(private_key=private_key, raw_string=bank_response_data):
    private_key = RSA.importKey(decodebytes(private_key.encode()))
    signer = PKCS1_v1_5.new(private_key)
    signature = signer.sign(SHA256.new(raw_string.encode()))
    return encodebytes(signature).decode().replace("\n", "")


def verify(data, signature, public_key):
    print(signature)
    key = RSA.importKey(decodebytes(public_key.encode()))
    hash_value = SHA256.new(data.encode())
    verifier = PKCS1_v1_5.new(key)
    if verifier.verify(hash_value, decodebytes(signature.encode())):
        print("The signature is authentic.")
    else:
        print("The signature is not authentic.")


verify(bank_response_data, sign(), public_key)
verify(bank_response_data, bank_response_signature, bank_public_key)

答案 1 :(得分:0)

下面是Java代码,使用相同的签名和公钥也可以正常工作。

import org.apache.commons.codec.digest.DigestUtils;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class MyTest {
    public static final String KEY_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "SHA256WithRSA";

public static void main(String[] args) {
    String data = "{\"head\":{\"vernbr\":\"1.0\",\"mchnbr\":\"BILL0003\",\"mchtyp\":\"BILLTYP\",\"trscod\":\"BILL001\",\"msgidc\":\"201805011230500001\",\"sigtim\":\"20190307115511\",\"sigalg\":\"SHA256WithRSA\",\"retcod\":\"F\",\"retmsg\":\"GWB2B006 源IP地址不在商户IP白名单中;商户编号:BILL0003;IP地址:123.139.40.150\"}}";

    String signature = "dnAFU2e5zFb8rJ1mXDNk5AG9UyujVIUArkBjb1Nonf7iMhZwHfHRO633eW5n7uELFnyJZk6Go2D6ovp4jEnIoA==";

    String cmbcRespSignature = "uZl0/5D694GnAd/G9OPRs9BSd9fb0fZGXSGThBtgLnKi+CDQAdasOX05mKazXZki0blXxApGYRAWa/kOrf+Wl0USfklx0G5w/eGERfMdRWpvtV3S2MBCH/H/0T81nKGgn8svkT/Trj7+Mc+e654Jn8IijGyV9m8Ak92hG2bLtbc=";
    String cmbcPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZs4l8Ez3F4MG0kF7RRSL+pn8MmxVE3nfdXzjx6d3rH8IfDbNvNRLS0X0b5iJnPyFO8sbbUo1Im4zX0M8XA0xnnviGyn5E6occiyUXJRgokphWb5BwaYdVhnLldctdimHoJTk3NFEQFav3guygR54i3tymrDc8lWtuG8EczVu8FwIDAQAB";

    try {
        boolean verify = verify(DigestUtils.sha256(data), cmbcPublicKey, cmbcRespSignature);
        if (verify) {

        }
    } catch (Exception e) {

    }
}

public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
    final Base64.Decoder decoder = Base64.getDecoder();
    final byte[] keyBytes = publicKey.getBytes("UTF-8");

    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoder.decode(keyBytes));

    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

    PublicKey pubKey = keyFactory.generatePublic(keySpec);

    Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    signature.initVerify(pubKey);
    signature.update(data);

    return signature.verify(decoder.decode(sign));
}

}

答案 2 :(得分:0)

最后,我得到了答案。 在Java

  

DigestUtils.sha256(data)进行了哈希处理,   SHA256WithRSA算法将进行哈希处理

所以我应该做的是在我的python代码中哈希2次