2017-06-22 91 views
1

在下面的代碼段我登錄使用充氣城堡的消息:在快活從ASN.1編碼檢索CMSSignedData城堡

import org.bouncycastle.cms.CMSProcessableByteArray; 
import org.bouncycastle.cms.CMSSignedData; 
import org.bouncycastle.cms.CMSSignedDataGenerator; 
import org.bouncycastle.cms.CMSTypedData; 
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.operator.ContentSigner; 
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; 
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; 
import org.bouncycastle.util.encoders.Base64; 

import java.io.FileInputStream; 

import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.security.KeyFactory; 
import java.security.PrivateKey; 
import java.security.Security; 
import java.security.cert.CertificateFactory; 
import java.security.cert.X509Certificate; 
import java.security.spec.PKCS8EncodedKeySpec; 

public class Sign { 

    public static void main(String[] args) throws Exception { 
     Security.addProvider(new BouncyCastleProvider()); 

     String certPath = "certPath"; 
     FileInputStream inPublic = new FileInputStream(certPath); 
     CertificateFactory factory = CertificateFactory.getInstance("X.509"); 
     X509Certificate cert = (X509Certificate) factory.generateCertificate(inPublic); 


     String keyPrivatePath = "keyPath"; 
     Path path = Paths.get(keyPrivatePath); 
     Files.readAllBytes(Paths.get(keyPrivatePath)); 
     PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Files.readAllBytes(Paths.get(keyPrivatePath))); 
     KeyFactory kf = KeyFactory.getInstance("RSA"); 
     PrivateKey privateKey = kf.generatePrivate(spec); 

     CMSProcessableByteArray msg = new CMSProcessableByteArray("My message".getBytes()); 
     CMSSignedDataGenerator sGen = new CMSSignedDataGenerator(); 

     ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(privateKey); 
     sGen.addSignerInfoGenerator(
       new JcaSignerInfoGeneratorBuilder(
         new JcaDigestCalculatorProviderBuilder().setProvider("BC").build() 
       ).build(sha1Signer, cert) 
     ); 

     CMSSignedData sd = sGen.generate(msg); 

     CMSTypedData cmsBytes = new CMSProcessableByteArray(sd.getEncoded()); 
     // How to reconstruct a CMSSignedData from cmsBytes again? 
     byte[] bytes = (byte[]) cmsBytes.getContent(); 
     CMSSignedData retrieved = new CMSSignedData(bytes); 
     System.out.println(retrieved.getSignedContent()); // Doesn't work, is null 
    } 
} 

我的問題是如何檢索原始CMSSignedData(想要閱讀原始消息,並驗證它),只使用該對象的ASN.1編碼的字節數組。

的原因,我問這個,是我想解密一定的加密和簽名的消息。我能夠解密該消息,但它導致ASN.1編碼的字節數組(其確實對應於我的原始消息),但我不能夠進一步處理該經解密的消息。

回答

0

您可以使用類org.bouncycastle.asn1.cms.ContentInfoorg.bouncycastle.asn1.ASN1Sequence

CMSTypedData cmsBytes = new CMSProcessableByteArray(sd.getEncoded()); 
byte[] bytes = (byte[]) cmsBytes.getContent(); 

// reconstruct CMSSignedData from the byte array 
ContentInfo ci = ContentInfo.getInstance(ASN1Sequence.fromByteArray(bytes)); 
CMSSignedData sig = new CMSSignedData(ci); 

另外請注意,您必須創建封裝在簽名內容的CMSSignedData,所以你必須改變這一點:

CMSSignedData sd = sGen.generate(msg); 

要這樣的:

CMSSignedData sd = sGen.generate(msg, true); 
+0

不幸的是,不WO RK :( 在這種情況下,'sig.getSignedContent()'產量空的,而不是我把消息的CMSProcessableByteArray ... –

+0

什麼版本您使用的?我使用BouncyCastle 1.57和Java 1.7 – 2017-06-22 18:36:48

+0

bouncyCastle 1.57和Java 1.8。它應該適用於Java 1.7嗎? –