2011-12-21 4 views
1

У меня есть некоторые проблемы с проверкой подписанного сообщения S/Mime с сертификатом x509. Это мой код:Проверка S/MIME с сертификатом x509

public class verifyMsg { 

private static void verify(SMIMESignedParser s) throws Exception { 

    Security.addProvider(new BouncyCastleProvider()); 
    System.out.println("wbilem"); 
    CertStore certs = s.getCertificatesAndCRLs("Collection", "BC"); 

    SignerInformationStore signers = s.getSignerInfos(); 
    Collection c = signers.getSigners(); 
    Iterator it = c.iterator(); 

    while (it.hasNext()) { 
     File f = new File("signature.crt"); 
     FileInputStream fis = new FileInputStream(f); 
     DataInputStream dis = new DataInputStream(fis); 
     byte[] keyBytes = new byte[(int) f.length()]; 
     dis.readFully(keyBytes); 
     dis.close(); 
     fis.close(); 
     SignerInformation signer = (SignerInformation) it.next(); 
     Collection certCollection = certs.getCertificates(signer.getSID()); 
     Iterator certIt = certCollection.iterator(); 
     FileInputStream fr = new FileInputStream("signature.crt"); 
     CertificateFactory cf = CertificateFactory.getInstance("X509"); 
     X509Certificate cert = (X509Certificate) cf.generateCertificate(fr); 


     if (signer.verify(cert, "BC")) { //problem is there... 
      System.out.println("signature verified"); 
     } else { 
      System.out.println("signature failed!"); 
     } 

    } 
} 

public static void main(String[] args) throws Exception { 
    Properties props = System.getProperties(); 
    Session session = Session.getDefaultInstance(props, null); 

    try { 
     FileInputStream fr = new FileInputStream("signature.crt"); 
     CertificateFactory cf = CertificateFactory.getInstance("X509"); 
     X509Certificate c = (X509Certificate) cf.generateCertificate(fr); 
     System.out.println("Read in the following certificate:"); 
     System.out.println("\tCertificate for: " + c.getSubjectDN()); 
     System.out.println("\tCertificate issued by: " + c.getIssuerDN()); 
     System.out.println("\tThe certificate is valid from " + c.getNotBefore() + " to " + c.getNotAfter()); 
     System.out.println("\tCertificate SN# " + c.getSerialNumber()); 
     System.out.println("\tGenerated with " + c.getSigAlgName()); 
     System.out.println(c.getPublicKey()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    try { 
     MimeMessage msg = new MimeMessage(session, new SharedFileInputStream("G:\\MIME.txt")); 
     if (msg.isMimeType("multipart/signed")) { 

      SMIMESignedParser s = new SMIMESignedParser((MimeMultipart) msg.getContent()); 
      System.out.println("Status:"); 
      verify(s); 
     } else if (msg.isMimeType("application/pkcs7-mime")) { 

      // in this case the content is wrapped in the signature block. 
      // 
      SMIMESignedParser s = new SMIMESignedParser(msg); 
      System.out.println("Status1:"); 
      verify(s); 
     } else { 
      System.err.println("Not a signed message!"); 
     } 

    } catch (MessagingException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (CMSException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

}

И у меня есть проблемы с этим исключением:

CMSSignerDigestMismatchException: сообщение-дайджест значения атрибута не соответствует расчетной стоимости. Я не знаю, что я делаю неправильно. Я использую jdk 1.4.2.

ответ

1

Я просто выясню, что проблема связана с сообщением. Я преобразовал массив байтов в строку, а затем эту строку во входной поток. Теперь я даю входной массив байтов без преобразования, и все в порядке :)

+0

Какое точное изменение вы сделали в своем коде, я сталкиваюсь с такой же проблемой, может помочь с фрагментом кода, что вы измените в своем коде. – Swapnil

0

Я решил эту проблему. Если вы подписываете данные с S/MIME, то согласно стандарту S/MIME у нас должна быть MIME-версия Content-Type. ..etc и заголовки отделены от сообщения, которое должно быть подписано пустой строкой. Большая часть времени, когда сообщение имеет тип «text/plain», мы не будем добавлять заголовки в сообщение, что очевидно. Но если вы используете S/MIME для подписи данных он будет искать стандартные заголовки S/MIME, и такие проблемы, как miss mach в дайджесте, будут возникать.

Добавить следующие заголовки сообщения перед подписанием MIME-версия: 1.0 Content-Type: text/plain;

Или просто добавьте одну пустую строку перед сообщением.

Над подходом работает отлично для меня.