Проблемы с проверкой файла pkcs7 - PullRequest
0 голосов
/ 02 марта 2011

У меня большая и странная проблема с файлами ценных бумаг PKCS7.Я создаю файл p7s, подобный тому, что предлагается в http://www.thatsjava.com/java-tech/85019/, где он создает файл и проверяет его, используя только библиотеки Sun.Это работает нормально.
Проблема начинается, когда я хочу проверить этот файл.Он возвращает это исключение:

java.security.SignatureException: Signature encoding error
        at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:185)
        at java.security.Signature$Delegate.engineVerify(Signature.java:1140)
        at java.security.Signature.verify(Signature.java:592)
        at sun.security.pkcs.SignerInfo.verify(SignerInfo.java:374)
        at sun.security.pkcs.PKCS7.verify(PKCS7.java:494)
        at sun.security.pkcs.PKCS7.verify(PKCS7.java:511)
        at sun.security.pkcs.PKCS7.verify(PKCS7.java:533)
        at firma.FirmaDigitalImpl.firmarCadenaSun(FirmaDigitalImpl.java:553)
        at firma.FirmaDigitalImpl.firmarCadena(FirmaDigitalImpl.java:249)
        at firma.FirmaDigitalImpl.firmarCadena(FirmaDigitalImpl.java:147)
        at firma.TestFirma.main(TestFirma.java:75)
Caused by: java.io.IOException: Sequence tag error
        at sun.security.util.DerInputStream.getSequence(DerInputStream.java:280)
        at sun.security.rsa.RSASignature.decodeSignature(RSASignature.java:209)
        at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:174)
        ... 10 more

Но проблемы возникают не всегда, а только с типом сертификатов, используемых для подписи.Я объясню лучше.У меня есть два сертификата (хранятся в смарт-карте), и первый работает нормально;Я создаю p7s, и затем я правильно проверяю, но второй сертификат позволяет мне создать файл p7s, но когда я проверяю его, он возвращает SignatureException.Я думал, что файл p7s был неправильным, но я проверил его с приложениями других, и он выглядит правильно.Кроме того, этот файл отправляется через веб-сервис и возвращает, что все в порядке!

И для получения дополнительной информации, если файл p7s создается с помощью различных инструментов (.net и capicom) и одного и того же сертификата, тогда я могу проверить правильность.

Я искал решение,но ничего.Я обнаружил такое же исключение в подобных ситуациях, но либо предложенное решение не работает для меня, либо оно не появляется.

Любой совет, чтобы найти решение, будет очень признателен.

Ответы [ 2 ]

1 голос
/ 18 марта 2011

Спустя более двух недель, я заметил, в чем проблема, хотя я не нашел полного решения.

Сначала я извлек проблему из файла PKCS7 и воспроизвел исключение со следующим исходным кодом:

import diz.firma.keyStore.SmartCard;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;

public class TestFirma3 {
public static void main(String args[]) throws Exception {
    //Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    SmartCard sm = new SmartCard();
    KeyStore ks = sm.loadKeyStore("1234");
    //KeyPair keyPair = generateKeyPair(999);


    byte[] data = "original".getBytes("UTF-8");
    //byte[] data = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 };
    //byte[] digitalSignature = signData(data, keyPair.getPrivate());
    byte[] digitalSignature = signData(data,
            (PrivateKey)ks.getKey(sm.getAlias(), null),ks.getProvider());

    boolean verified;

    //verified = verifySig(data, keyPair.getPublic(), digitalSignature);
    verified = verifySig(data, ks.getCertificate(sm.getAlias()).
            getPublicKey(),ks.getProvider(), digitalSignature);
    System.out.println("verified:" + verified) ;

    //keyPair = generateKeyPair(888);
    //verified = verifySig(data, keyPair.getPublic(), digitalSignature);
    //System.out.println(verified);

  }

  public static byte[] signData(byte[] data, PrivateKey key,Provider p) throws Exception {
    Signature signer = Signature.getInstance("SHA1withRSA",p);
    //Signature signer = Signature.getInstance("SHA1withRSA",Security.getProviders()[10]);

    signer.initSign(key);
    signer.update(data);
    return (signer.sign());
  }

  public static boolean verifySig(byte[] data, PublicKey key, Provider p, byte[] sig) throws Exception {
    Signature signer = Signature.getInstance("SHA1withRSA",p);
    //Signature signer = Signature.getInstance("SHA1withRSA");
    signer.initVerify(key);
    signer.update(data);

    boolean valido = false;
    try{
        valido = signer.verify(sig);
    }catch(Exception e){
        e.printStackTrace();
        valido = false;
    }
    return valido;

  }

  public static KeyPair generateKeyPair(long seed) throws Exception {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("DSA");
    SecureRandom rng = SecureRandom.getInstance("SHA1PRNG", "SUN");
    rng.setSeed(seed);
    keyGenerator.initialize(1024, rng);

    return (keyGenerator.generateKeyPair());
  }
}

В этом коде (извлеченном из примера в сети) я изменил ключ генератора и взял его со своей карты. Я снова получил исключение, не используя файлы PKCS7.

Рассматривая всех провайдеров (с помощью Security.getProviders () вы можете получить их всех; они определены в файле java.security, но его можно добавлять или извлекать во время выполнения), и я использовал всех для подписи и проверить, я узнал, что:

  1. Если ни один поставщик не выбран при создании экземпляра Signature, он по умолчанию использует SunRsaSign.
  2. Моя подпись подтверждена 2 провайдерами:
    a) С поставщиком SunMSCAPI, который использует Microsoft Crypt API.
    б) с провайдером, созданным устройством чтения смарт-карт, в моем случае Siemens.
  3. Считывание другой смарт-карты, не принадлежащей Siemens, проверяется с помощью SunRsaSign и SunJSSE.

В данный момент я выясняю проблему и работаю, используя SunMSCAPI для проверки, но мне нужно выполнить проверку на машине IBM. Программное обеспечение Siemens предоставляет возможность установки в Unix, но я не могу заставить его работать. И, используя SunMSCAPI, я полагаю, он недоступен для IBM.

Итак, мне нужно найти поставщика, который правильно проверяет в IMB подпись, которую SunRsaSign возвращает SignatureException.

1 голос
/ 02 марта 2011

Это может быть проблема кодирования: текст или двоичный файл.PKCS7 может быть либо в двоичном формате с кодировкой DER, либо в формате PEM (который является DER-кодированием с кодировкой base64).Откройте файлы в текстовом редакторе (например, в блокноте) и посмотрите, является ли тот, который работает, двоичным или текстовым.

...