Длина подписи не верна: получил 768, но ожидал 512, в Java проверьте - PullRequest
4 голосов
/ 07 марта 2019

Я уже публиковал аналогичный вопрос о том, как загрузить ключи RSA в Java. Смотрите лучший ответ на этот вопрос, чтобы полностью понять первую часть моего кода (я имею в виду метод getPulicKey).

private static PublicKey getPublicKey(String publicKey)
        throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
    try (PEMParser pp = new PEMParser(new StringReader(publicKey))) {
        SubjectPublicKeyInfo subjPubKeyInfo = (SubjectPublicKeyInfo) pp.readObject();
        RSAKeyParameters rsa = (RSAKeyParameters) PublicKeyFactory.createKey(subjPubKeyInfo);

        RSAPublicKeySpec rsaSpec = new RSAPublicKeySpec(rsa.getModulus(), rsa.getExponent());
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PublicKey myKey = kf.generatePublic(rsaSpec);
        System.out.println(myKey);
        return myKey;
    }
}

Метод проверки (ниже) вызывает следующее исключение

Длина подписи не верна: получил 768, но ожидал 512, в Java проверьте

В следующем коде я декодирую подпись, поскольку полагаю, что это Base64, но я не уверен, извините. Я не знаю, смогу ли я показать вам подпись и объект. Подпись представляет собой последовательность из 1024 цифр и цифр. Это не заканчивается на "=". Объект, который я должен проверить, - это объект json в формате String. Ниже приведен метод, который я написал для проверки объекта String с использованием знака и publicKey. Вызывает вышеуказанный метод getPublicKey (...).

public static boolean verify(String object, String sign, String publicKey) throws NoSuchAlgorithmException,
        InvalidKeySpecException, IOException, InvalidKeyException, SignatureException {
    //object to be verified
    //sign is the signature stored in the postgres DB
    //publicKey is the public key stored in the postgres DB
    Signature signature = Signature.getInstance("SHA256withRSA");
    signature.initVerify(getPublicKey(publicKey));
    byte[] objectBytes = Base64.getEncoder().encode(object.getBytes("utf-8"));
    signature.update(objectBytes);
    byte[] signBytes = Base64.getDecoder().decode(sign.getBytes("utf-8"));
    System.out.println(signBytes.length); //this line prints 768, with decode. 1024, otherwhise
    return signature.verify(signBytes);
}

EDIT:

Мои коллеги по работе используют следующие два метода nodejs (verifySign и createSign).

В следующем коде nodejs (где есть методы коллег) я пишу «createSign» сообщение «поддельное сообщение». Знак следующий:

5f188225c68dee2ce8de588dfaccb667710da94abb5388deabfe3ad83f7a94a72ee4a3c8c51be26c5b58cdec8c82cf8135c478ad609b7985496e201b23de6c5d03e93dcd9df7b5e2315efbfd2ff6496b0aea3b425bb99c912a16aeb5efb6cefc1e175c32aaf16af3a2baca5b54f974af0f14c853228bc06410e7ad1b2b0ecec19f5aed151389bd9ccebd5e998159d5205d81a7c7e37b502df3eb5229a5fd3492680576ebfa1e76b7c47fb757a9bfb18aa9ea0b71512ab9e1afc8e551ebf6d74a042bd447233953efbf374a3a6a210ead2019b8cc8548bb304979b4bfdc90dce644cb109bbddb75dda9df1322fd8e08ef1144e870324f34d4c826d9a4b64be0442aedc6f3d5f571d7336af212825c4e0216aa5eabab6218d685a3e73d81693149b45af5f1857c4a0e50b396d1a2ea5a3effafcc4e124fd23d0427abfe5509357936ef5e7c7ca4476d6a5ae7a26e9563923a03d0780f0d897039d4d3aa2ce49dc84b31907a50045456acb57edd11a896632969245d0f97fd88dace7eb256099bbc4eedf52b5d53b481b2aeb829101d0089903ea9c3621bcbd763962b84ad57407623b576cc6a9c3328d85e0f7dd78565cd39a6648a68dd6f4334dd3a68e48491ae655601a5c9be7673ae0d3f955431fb21f33c0178ecb9067072a6b1e360ee77a45f8e855e6c545276aefc7ae70b5c7e0f1e c0b66460575e3386f8a4bbf7fd3704

Затем я проверяю его с помощью открытого ключа pk (см. Ниже).

const PASSPHRASE_KEY = "...";
const crypto = require('crypto');

const prk = "...";

const pk = "-----BEGIN RSA PUBLIC KEY-----\r\n" + 
            "MIICCgKCAgEA1ht0OqZpP7d/05373OE7pB7yCVGNGzkUEuCneyfOzps6iA03NbvI\r\n" + 
            "1ZL0Jpp/N3AW73lGdhaoa3X3JE4GsI/bsToVLQwTKmIOC4yjTvBctmFEoyhhTfxW\r\n" + 
            "s1UHZKl4XZ/7THbRlKHhRaTKyfDAbikkMAxNT/qutLAPjnN1qOwjb1oRq52NP6FJ\r\n" + 
            "KWTTikz4UeOHroX+Xthn2fJSJDlQ4YMdBbgrZVx5JcHKNuPTKRf5gI8QQKMSA9Q9\r\n" + 
            "QJRE5OGp7b6dG14ZmOUnUxb00Mp20LgcaGPcuWU+oFsbQaF6W4G4bdkSZRJJXhSg\r\n" + 
            "d4Q7mahpar94/gnztJmth0GzqTWUYyZIWNqIFoMwuOgeaiDV43zb3uLsRVpRKYYy\r\n" + 
            "esmzcOy/jTScVLRCD8QRyu9B2wgCkNAVztQOXPCOOa4O1LlVQWaecIs4WPhOqDhi\r\n" + 
            "KTBhyVkpC1TrrBkp+QMqMqWll1OyVb6k/7uV0qE/i6rHJtjo5v9bcIgYzswyx9CD\r\n" + 
            "9PKl2Q0L0Jg7TMG+yLDIrLfGeuSeEc4XYJzN7bJcCeiizzu5iU9dQUkrncOrq9jn\r\n" + 
            "Ub2pM/+A+JqIsoPK3IY/pJKqH4JYpGKhO1iPQF6iXIZT1r3ZgJUSQtzSeyYqhkla\r\n" + 
            "2uR2BsbPbDqebCuXm3lAsY5w+dujijcn96PKwYha1LsK5sACHuJ79AMCAwEAAQ==\r\n" + 
            "-----END RSA PUBLIC KEY-----\r\n" + 
            "";

function createSign(pvt_key, data_unsigned) {
    //Create a SHA256 sign generator
    const signer = crypto.createSign('SHA256');

    //Update context with data to sign
    signer.update(data_unsigned);

    //Sign the document based to user's private key
    return signer.sign({
        key: pvt_key,
        passphrase: PASSPHRASE_KEY
        },
        'hex'
    );
}

function verifySign(pub_key, signed_data, signature) {
  const verifier = crypto.createVerify('sha256');

  //Update context with data to verify
  verifier.update(signed_data);

  //Verify sign with user's public key
  const verified = verifier.verify(
    pub_key,
    signature,
    'hex'
  );

  //Send result
  return verified;
}

const phrase = "fake message";
var signMade = createSign(prk, phrase);
console.log("my signature: " + signMade);
//The signature is 5f188225c68dee2ce8de588dfaccb667710da94abb5388deabfe3ad83f7a94a72ee4a3c8c51be26c5b58cdec8c82cf8135c478ad609b7985496e201b23de6c5d03e93dcd9df7b5e2315efbfd2ff6496b0aea3b425bb99c912a16aeb5efb6cefc1e175c32aaf16af3a2baca5b54f974af0f14c853228bc06410e7ad1b2b0ecec19f5aed151389bd9ccebd5e998159d5205d81a7c7e37b502df3eb5229a5fd3492680576ebfa1e76b7c47fb757a9bfb18aa9ea0b71512ab9e1afc8e551ebf6d74a042bd447233953efbf374a3a6a210ead2019b8cc8548bb304979b4bfdc90dce644cb109bbddb75dda9df1322fd8e08ef1144e870324f34d4c826d9a4b64be0442aedc6f3d5f571d7336af212825c4e0216aa5eabab6218d685a3e73d81693149b45af5f1857c4a0e50b396d1a2ea5a3effafcc4e124fd23d0427abfe5509357936ef5e7c7ca4476d6a5ae7a26e9563923a03d0780f0d897039d4d3aa2ce49dc84b31907a50045456acb57edd11a896632969245d0f97fd88dace7eb256099bbc4eedf52b5d53b481b2aeb829101d0089903ea9c3621bcbd763962b84ad57407623b576cc6a9c3328d85e0f7dd78565cd39a6648a68dd6f4334dd3a68e48491ae655601a5c9be7673ae0d3f955431fb21f33c0178ecb9067072a6b1e360ee77a45f8e855e6c545276aefc7ae70b5c7e0f1ec0b66460575e3386f8a4bbf7fd3704
console.log("was it me to sign that?");
var res = verifySign(pk, phrase, signMade);
console.log(res);

Возвращает истину. Однако, если я перейду к методу java, проверьте следующие (те же самые) параметры:

  1. object = "поддельное сообщение"
  2. знак = 5f188225c68dee2ce8de588dfaccb667710da94abb5388deabfe3ad83f7a94a72ee4a3c8c51be26c5b58cdec8c82cf8135c478ad609b7985496e201b23de6c5d03e93dcd9df7b5e2315efbfd2ff6496b0aea3b425bb99c912a16aeb5efb6cefc1e175c32aaf16af3a2baca5b54f974af0f14c853228bc06410e7ad1b2b0ecec19f5aed151389bd9ccebd5e998159d5205d81a7c7e37b502df3eb5229a5fd3492680576ebfa1e76b7c47fb757a9bfb18aa9ea0b71512ab9e1afc8e551ebf6d74a042bd447233953efbf374a3a6a210ead2019b8cc8548bb304979b4bfdc90dce644cb109bbddb75dda9df1322fd8e08ef1144e870324f34d4c826d9a4b64be0442aedc6f3d5f571d7336af212825c4e0216aa5eabab6218d685a3e73d81693149b45af5f1857c4a0e50b396d1a2ea5a3effafcc4e124fd23d0427abfe5509357936ef5e7c7ca4476d6a5ae7a26e9563923a03d0780f0d897039d4d3aa2ce49dc84b31907a50045456acb57edd11a896632969245d0f97fd88dace7eb256099bbc4eedf52b5d53b481b2aeb829101d0089903ea9c3621bcbd763962b84ad57407623b576cc6a9c3328d85e0f7dd78565cd39a6648a68dd6f4334dd3a68e48491ae655601a5c9be7673ae0d3f955431fb21f33c0178ecb9067072a6b1e360ee77a45f8e855e6c545276aefc7ae70b5 c7e0f1ec0b66460575e3386f8a4bbf7fd3704
  3. publicKey скопирован из pk (см. Код узла выше)

Java вызывает исключение:

Длина подписи не верна: получил 768, но ожидал 512 Длина подписи не верна.

1 Ответ

5 голосов
/ 08 марта 2019

Вы рассматриваете подпись так, как будто она закодирована в base64, но это не так - это просто шестнадцатеричный код.

1024 символа представляют 768 байтов в кодировке base64 или 512 байтов в шестнадцатеричном коде.

Просто декодируйте, используя hex вместо base64, и все должно быть в порядке.

Намекните, что это правильно, а также отметьте, что каждый символ вашей подписи является действительной шестнадцатеричной цифрой (что было бы крайне маловероятно, если это на самом деле base64):

return signer.sign({
    key: pvt_key,
    passphrase: PASSPHRASE_KEY
    },
    'hex' // Note this use of 'hex'...
);
...