001    // Copyright (C) 2002 IAIK
002    // https://jce.iaik.tugraz.at
003    //
004    // Copyright (C) 2003 - 2025 Stiftung Secure Information and
005    //                           Communication Technologies SIC
006    // https://sic.tech
007    //
008    // All rights reserved.
009    //
010    // Redistribution and use in source and binary forms, with or without
011    // modification, are permitted provided that the following conditions
012    // are met:
013    // 1. Redistributions of source code must retain the above copyright
014    //    notice, this list of conditions and the following disclaimer.
015    // 2. Redistributions in binary form must reproduce the above copyright
016    //    notice, this list of conditions and the following disclaimer in the
017    //    documentation and/or other materials provided with the distribution.
018    //
019    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
020    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
023    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
024    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
025    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
027    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
028    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
029    // SUCH DAMAGE.
030    
031    // Copyright (C) 2002 IAIK
032    // https://sic.tech/
033    //
034    // Copyright (C) 2003 - 2025 Stiftung Secure Information and 
035    //                           Communication Technologies SIC
036    // https://sic.tech/
037    //
038    // All rights reserved.
039    //
040    // This source is provided for inspection purposes and recompilation only,
041    // unless specified differently in a contract with IAIK. This source has to
042    // be kept in strict confidence and must not be disclosed to any third party
043    // under any circumstances. Redistribution in source and binary forms, with
044    // or without modification, are <not> permitted in any case!
045    //
046    // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
047    // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
048    // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
049    // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
050    // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
051    // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
052    // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
053    // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
054    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
055    // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
056    // SUCH DAMAGE.
057    //
058    // $Header: /IAIK-CMS/current/src/demo/cms/signedData/PssSignedDataDemo.java 21    12.02.25 17:58 Dbratko $
059    // $Revision: 21 $
060    //
061    
062    package demo.cms.signedData;
063    
064    import java.io.ByteArrayInputStream;
065    import java.io.ByteArrayOutputStream;
066    import java.io.IOException;
067    import java.io.InputStream;
068    import java.security.AlgorithmParameters;
069    import java.security.InvalidAlgorithmParameterException;
070    import java.security.MessageDigest;
071    import java.security.NoSuchAlgorithmException;
072    import java.security.PrivateKey;
073    import java.security.SignatureException;
074    import java.security.cert.Certificate;
075    import java.security.spec.InvalidParameterSpecException;
076    
077    import demo.DemoUtil;
078    import demo.keystore.CMSKeyStore;
079    import iaik.asn1.ObjectID;
080    import iaik.asn1.structures.AlgorithmID;
081    import iaik.asn1.structures.Attribute;
082    import iaik.cms.CMSException;
083    import iaik.cms.IssuerAndSerialNumber;
084    import iaik.cms.SecurityProvider;
085    import iaik.cms.SignedData;
086    import iaik.cms.SignedDataStream;
087    import iaik.cms.SignerInfo;
088    import iaik.cms.SubjectKeyID;
089    import iaik.cms.attributes.CMSContentType;
090    import iaik.cms.attributes.SigningTime;
091    import iaik.pkcs.pkcs1.MGF1ParameterSpec;
092    import iaik.pkcs.pkcs1.MaskGenerationAlgorithm;
093    import iaik.pkcs.pkcs1.RSAPssParameterSpec;
094    import iaik.utils.Util;
095    import iaik.x509.X509Certificate;
096    import iaik.x509.X509ExtensionException;
097    
098    /**
099     * This class demonstrates the CMS SignedData implementation for
100     * the RSA-PSS (PKCS#1v2.1) algorithm.
101     */
102    public class PssSignedDataDemo {
103    
104      // certificate of user 1
105      X509Certificate user1;
106      // private key of user 1
107      PrivateKey user1_pk;
108      // certificate of user 2
109      X509Certificate user2;
110      // private key of user 2
111      PrivateKey user2_pk;
112     
113      // a certificate chain containing the user certs + CA
114      Certificate[] certificates;
115      Certificate[] certs;
116      Certificate[] user1Certs;
117      
118      // just for attribute certificate testing
119      PrivateKey issuer1_pk;
120    
121      /**
122       * Setups the demo certificate chains.
123       * 
124       * Keys and certificate are retrieved from the demo KeyStore.
125       * 
126       * @throws IOException if an file read error occurs
127       */
128      public PssSignedDataDemo() throws IOException {
129        
130        System.out.println();
131        System.out.println("**********************************************************************************");
132        System.out.println("*                             PssSignedDataDemo                                  *");
133        System.out.println("* (shows the usage of the CMS SignedData type with the RSA PSS signature scheme) *");
134        System.out.println("**********************************************************************************");
135        System.out.println();
136        
137        // add all certificates to the list
138        user1Certs = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
139        user1 = (X509Certificate)user1Certs[0];
140        user1_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
141        user2 = CMSKeyStore.getCertificateChain(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1)[0];
142        user2_pk = CMSKeyStore.getPrivateKey(CMSKeyStore.RSA, CMSKeyStore.SZ_2048_SIGN_1);
143          
144        certs = user1Certs;
145        certificates = new Certificate[certs.length+1];
146        System.arraycopy(certs, 0, certificates, 0, certs.length);
147        certificates[certs.length] = user2;
148      }
149      
150      /**
151       * Creates a CMS <code>SignedData</code> object.
152       * <p>
153       *
154       * @param message the message to be signed, as byte representation
155       * @param mode the transmission mode, either IMPLICIT or EXPLICIT
156       * @return the BER encoding of the <code>SignedData</code> object just created
157       * @throws CMSException if the <code>SignedData</code> object cannot
158       *                          be created
159       * @throws IOException if some stream I/O error occurs
160       */
161      public byte[] createSignedDataStream(byte[] message, int mode) throws CMSException, IOException  {
162        
163        System.out.print("Create a new message signed by user 1 :");
164       
165        // we are testing the stream interface
166        ByteArrayInputStream is = new ByteArrayInputStream(message);
167        // create a new SignedData object which includes the data
168        SignedDataStream signed_data = new SignedDataStream(is, mode);
169        
170        // SignedData shall include the certificate chain for verifying
171        signed_data.setCertificates(certificates);
172        
173        // cert at index 0 is the user certificate
174        IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(user1);
175    
176        // create a new SignerInfo for RSA-PSS with default parameters
177        SignerInfo signer_info = new SignerInfo(issuer, 
178                                                (AlgorithmID)AlgorithmID.sha256.clone(),
179                                                (AlgorithmID)AlgorithmID.rsassaPss.clone(),
180                                                user1_pk);
181        // create some signed attributes
182        // the message digest attribute is automatically added
183        Attribute[] attributes = new Attribute[2];
184        try {
185          // content type is data
186          CMSContentType contentType = new CMSContentType(ObjectID.cms_data);
187          attributes[0] = new Attribute(contentType);
188          // signing time is now
189          SigningTime signingTime = new SigningTime();
190          attributes[1] = new Attribute(signingTime);
191        } catch (Exception ex) {
192          throw new CMSException("Error creating attribute: " + ex.toString());   
193        }
194          
195        // set the attributes
196        signer_info.setSignedAttributes(attributes);
197        // finish the creation of SignerInfo by calling method addSigner
198        try {
199          signed_data.addSignerInfo(signer_info);
200          // another SignerInfo without signed attributes and RSA-PSS with user defined parameters
201          AlgorithmID hashID = (AlgorithmID)AlgorithmID.sha256.clone();
202          AlgorithmID mgfID = (AlgorithmID)AlgorithmID.mgf1.clone();
203          int saltLength = 32;
204          AlgorithmID rsaPssID = null;
205          try {
206            rsaPssID = createPssAlgorithmID(hashID, mgfID, saltLength);
207          } catch (Exception ex) {
208            throw new CMSException("Error creating PSS parameters: " + ex.toString());
209          }   
210          signer_info = new SignerInfo(new SubjectKeyID(user2), 
211                                       hashID, 
212                                       rsaPssID,
213                                       user2_pk);
214          
215          // the message digest itself is protected
216          signed_data.addSignerInfo(signer_info);
217    
218        } catch (NoSuchAlgorithmException ex) {
219          throw new CMSException("No implementation for signature algorithm: "+ex.getMessage());
220        } catch (X509ExtensionException ex) {
221          throw new CMSException("Cannot create SubjectKeyID for user2 : " + ex.getMessage());
222        }
223    
224        // write the data through SignedData to any out-of-band place
225        if (mode == SignedDataStream.EXPLICIT) {
226          InputStream data_is = signed_data.getInputStream();
227          byte[] buf = new byte[1024];
228          int r;
229          while ((r = data_is.read(buf)) > 0) {
230            ;   // skip data
231          }  
232        }
233    
234        // return the SignedData as DER encoded byte array with block size 2048
235        ByteArrayOutputStream os = new ByteArrayOutputStream();
236        signed_data.writeTo(os, 2048);
237        return os.toByteArray();
238      }
239      
240    
241      /**
242       * Parses a CMS <code>SignedData</code> object and verifies the signatures
243       * for all participated signers.
244       *
245       * @param signedData <code>SignedData</code> object as BER encoded byte array
246       * @param message the message which was transmitted out-of-band (if explicit signed),
247       *                otherwise <code>null</code> (implicit signed)
248       *
249       * @return the inherent message as byte array
250       * @throws CMSException if any signature does not verify
251       * @throws IOException if some stream I/O error occurs
252       */
253      public byte[] getSignedDataStream(byte[] signedData, byte[] message) throws CMSException, IOException {
254    
255        // we are testing the stream interface
256        ByteArrayInputStream is = new ByteArrayInputStream(signedData);
257        // create the SignedData object
258        SignedDataStream signed_data = new SignedDataStream(is);
259        
260        if (signed_data.getMode() == SignedDataStream.EXPLICIT) {
261          // explicitly signed; set the data stream for digesting the message
262          signed_data.setInputStream(new ByteArrayInputStream(message));
263        }
264    
265        // get an InputStream for reading the signed content
266        InputStream data = signed_data.getInputStream();
267        ByteArrayOutputStream os = new ByteArrayOutputStream();
268        Util.copyStream(data, os, null);
269    
270        System.out.println("SignedData contains the following signer information:");
271        SignerInfo[] signer_infos = signed_data.getSignerInfos();
272        
273        int numberOfSignerInfos = signer_infos.length;
274        if (numberOfSignerInfos == 0) {
275          String warning = "Warning: Unsigned message (no SignerInfo included)!";  
276          System.err.println(warning);
277          throw new CMSException(warning);
278        } else {
279          for (int i = 0; i < numberOfSignerInfos; i++) {
280            
281            try {
282              // verify the signed data using the SignerInfo at index i
283              X509Certificate signer_cert = signed_data.verify(i);
284              // if the signature is OK the certificate of the signer is returned
285              System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
286              // get signed attributes
287              SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime);
288              if (signingTime != null) {
289                System.out.println("This message has been signed at " + signingTime.get());
290              } 
291              CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType);
292              if (contentType != null) {
293                System.out.println("The content has CMS content type " + contentType.get().getName());
294              }
295            } catch (SignatureException ex) {
296              // if the signature is not OK a SignatureException is thrown
297              System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getSignerIdentifier()).getSubjectDN());
298              throw new CMSException(ex.toString());
299            } 
300          }  
301        
302          // now check alternative signature verification
303          System.out.println("Now check the signature assuming that no certs have been included:");
304          try {
305             SignerInfo signer_info = signed_data.verify(user1);
306              // if the signature is OK the certificate of the signer is returned
307              System.out.println("Signature OK from signer: "+user1.getSubjectDN());
308              
309          } catch (SignatureException ex) {
310              // if the signature is not OK a SignatureException is thrown
311              System.out.println("Signature ERROR from signer: "+user1.getSubjectDN());
312              throw new CMSException(ex.toString());
313          }
314        
315        
316          try {
317            SignerInfo signer_info = signed_data.verify(user2);
318            // if the signature is OK the certificate of the signer is returned
319            System.out.println("Signature OK from signer: "+signed_data.getCertificate(signer_info.getSignerIdentifier()).getSubjectDN());
320              
321          } catch (SignatureException ex) {
322            // if the signature is not OK a SignatureException is thrown
323            System.out.println("Signature ERROR from signer: "+user2.getSubjectDN());
324            throw new CMSException(ex.toString());
325          }
326          // in practice we also would validate the signer certificate(s)  
327        }
328            
329        return os.toByteArray();
330      }
331      
332      
333      
334      /**
335       * Creates a CMS <code>SignedData</code> object.
336       * <p>
337       *
338       * @param message the message to be signed, as byte representation
339       * @param mode the mode, either SignedData.IMPLICIT or SignedData.EXPLICIT
340       * @return the DER encoded <code>SignedData</code> object 
341       * @throws CMSException if the <code>SignedData</code> object cannot
342       *                          be created
343       */
344      public byte[] createSignedData(byte[] message, int mode) throws CMSException {
345        
346        System.out.println("Create a new message signed by user 1 :");
347      
348        // create a new SignedData object which includes the data
349        SignedData signed_data = new SignedData(message, mode);
350        
351        // SignedData shall include the certificate chain for verifying
352        signed_data.setCertificates(certificates);
353      
354        // cert at index 0 is the user certificate
355        IssuerAndSerialNumber issuer = new IssuerAndSerialNumber(user1);
356    
357        // create a new SignerInfo for RSA-PSS with default parameters
358        SignerInfo signer_info = new SignerInfo(issuer, 
359                                                (AlgorithmID)AlgorithmID.sha256.clone(),
360                                                (AlgorithmID)AlgorithmID.rsassaPss.clone(),
361                                                user1_pk);
362        
363        // create some signed attributes
364        // the message digest attribute is automatically added
365        Attribute[] attributes = new Attribute[2];
366        try {
367          // content type is data
368          CMSContentType contentType = new CMSContentType(ObjectID.cms_data);
369          attributes[0] = new Attribute(contentType);
370          // signing time is now
371          SigningTime signingTime = new SigningTime();
372          attributes[1] = new Attribute(signingTime);
373        } catch (Exception ex) {
374          throw new CMSException("Error creating attribute: " + ex.toString());   
375        }
376        
377        // set the attributes
378        signer_info.setSignedAttributes(attributes);
379        // finish the creation of SignerInfo by calling method addSigner
380        try {
381          signed_data.addSignerInfo(signer_info);
382    
383          // another SignerInfo without signed attributes and RSA-PSS with user defined parameters
384          AlgorithmID hashID = (AlgorithmID)AlgorithmID.sha256.clone();
385          AlgorithmID mgfID = (AlgorithmID)AlgorithmID.mgf1.clone();
386          int saltLength = 32;
387          AlgorithmID rsaPssID = null;
388          try {
389            rsaPssID = createPssAlgorithmID(hashID, mgfID, saltLength);
390          } catch (Exception ex) {
391            throw new CMSException("Error creating PSS parameters: " + ex.toString());
392          }   
393          signer_info = new SignerInfo(new SubjectKeyID(user2), 
394                                       hashID, 
395                                       rsaPssID,
396                                       user2_pk);
397      
398          signed_data.addSignerInfo(signer_info);
399    
400        } catch (NoSuchAlgorithmException ex) {
401          throw new CMSException("No implementation for signature algorithm: "+ex.getMessage());
402        } catch (X509ExtensionException ex) {
403          throw new CMSException("Cannot create SubjectKeyID for user2 : " + ex.getMessage());
404        }     
405        return signed_data.getEncoded();
406      }
407      
408      
409      /**
410       * Parses a CMS <code>SignedData</code> object and verifies the signatures
411       * for all participated signers.
412       *
413       * @param encoding the DER encoded <code>SignedData</code> object
414       * @param message the message which was transmitted out-of-band (if explicit signed),
415       *                otherwise <code>null</code> (implicit signed)
416       *
417       * @return the inherent message as byte array
418       * @throws CMSException if any signature does not verify
419       * @throws IOException if some stream I/O error occurs
420       */
421      public byte[] getSignedData(byte[] encoding, byte[] message) throws CMSException, IOException {
422        
423        // create the SignedData object
424        SignedData signed_data = new SignedData(new ByteArrayInputStream(encoding));
425        if (signed_data.getMode() == SignedData.EXPLICIT) {
426          // explicitly signed; set the data stream for digesting the message
427          signed_data.setContent(message);
428        }
429       
430        System.out.println("SignedData contains the following signer information:");
431        SignerInfo[] signer_infos = signed_data.getSignerInfos();
432        
433        int numberOfSignerInfos = signer_infos.length;
434        if (numberOfSignerInfos == 0) {
435          String warning = "Warning: Unsigned message (no SignerInfo included)!";  
436          System.err.println(warning);
437          throw new CMSException(warning);
438        } else {
439          for (int i = 0; i < numberOfSignerInfos; i++) {
440            try {
441              // verify the signed data using the SignerInfo at index i
442              X509Certificate signer_cert = signed_data.verify(i);
443              // if the signature is OK the certificate of the signer is returned
444              System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
445              // get signed attributes
446              SigningTime signingTime = (SigningTime)signer_infos[i].getSignedAttributeValue(ObjectID.signingTime);
447              if (signingTime != null) {
448                System.out.println("This message has been signed at " + signingTime.get());
449              } 
450              CMSContentType contentType = (CMSContentType)signer_infos[i].getSignedAttributeValue(ObjectID.contentType);
451              if (contentType != null) {
452                System.out.println("The content has CMS content type " + contentType.get().getName());
453              }
454            } catch (SignatureException ex) {
455               // if the signature is not OK a SignatureException is thrown
456               System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getSignerIdentifier()).getSubjectDN());
457               throw new CMSException(ex.toString());
458            } 
459          }      
460        
461          // now check alternative signature verification
462          System.out.println("Now check the signature assuming that no certs have been included:");
463          try {
464            SignerInfo signer_info = signed_data.verify(user1);
465            // if the signature is OK the certificate of the signer is returned
466            System.out.println("Signature OK from signer: "+signed_data.getCertificate(signer_info.getSignerIdentifier()).getSubjectDN());
467              
468          } catch (SignatureException ex) {
469            // if the signature is not OK a SignatureException is thrown
470            System.out.println("Signature ERROR from signer: "+user1.getSubjectDN());
471            throw new CMSException(ex.toString());
472          }
473          try {
474            SignerInfo signer_info = signed_data.verify(user2);
475            // if the signature is OK the certificate of the signer is returned
476            System.out.println("Signature OK from signer: "+signed_data.getCertificate(signer_info.getSignerIdentifier()).getSubjectDN());
477              
478          } catch (SignatureException ex) {
479            // if the signature is not OK a SignatureException is thrown
480            System.out.println("Signature ERROR from signer: "+user2.getSubjectDN());
481            throw new CMSException(ex.toString());
482          }
483          // in practice we also would validate the signer certificate(s)  
484        }
485        return signed_data.getContent();
486      }
487      
488      /**
489       * Creates an RSA-PSS AlgorithmID with the supplied parameters (hash algorithm id,
490       * mask generation function, salt length).
491       *
492       * @param hashID the hash algorithm to be used
493       * @param mgfID the mask generation function to be used
494       * @param saltLength the salt length to be used
495       *
496       * @return the RSA-PSS algorithm id with the given parameters 
497       *
498       * @throws InvalidAlgorithmParameterException if the parameters cannot be created/set
499       * @throws NoSuchAlgorithmException if there is no AlgorithmParameters implementation
500       *                                     for RSA-PSS
501       */
502      public static AlgorithmID createPssAlgorithmID(AlgorithmID hashID, AlgorithmID mgfID, int saltLength)
503        throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
504        
505        SecurityProvider provider = SecurityProvider.getSecurityProvider();
506        AlgorithmID rsaPssID = (AlgorithmID)AlgorithmID.rsassaPss.clone();
507        mgfID.setParameter(hashID.toASN1Object());
508        // create a RSAPssParameterSpec
509        RSAPssParameterSpec pssParamSpec = new RSAPssParameterSpec(hashID, mgfID, saltLength);
510        // optionally set hash and mgf engines
511        MessageDigest hashEngine = provider.getMessageDigest(hashID);
512        pssParamSpec.setHashEngine(hashEngine);
513        MaskGenerationAlgorithm mgfEngine = provider.getMaskGenerationAlgorithm(mgfID);
514        MGF1ParameterSpec mgf1Spec = new MGF1ParameterSpec(hashID);
515        mgf1Spec.setHashEngine(hashEngine);
516        mgfEngine.setParameters(mgf1Spec);
517        pssParamSpec.setMGFEngine(mgfEngine);
518    
519        AlgorithmParameters pssParams = null;
520        try {
521          pssParams = provider.getAlgorithmParameters(SecurityProvider.IMPLEMENTATION_NAME_RSA_PSS);
522          pssParams.init(pssParamSpec);
523        } catch (InvalidParameterSpecException ex) {
524          throw new InvalidAlgorithmParameterException("Cannot init PSS params: " + ex.getMessage());  
525        }    
526       
527        rsaPssID.setAlgorithmParameters(pssParams);
528        return rsaPssID;
529      }  
530    
531      /**
532       * Tests the CMS SignedData implementation for
533       * the RSA-PSS (PKCS#1v2.1) algorithm.
534       */
535      public void start() {
536         // the test message
537        String m = "This is the test message.";
538        System.out.println("Test message: \""+m+"\"");
539        System.out.println();
540        byte[] message = m.getBytes();
541       
542        try {
543          byte[] encoding;
544          byte[] received_message = null;
545          System.out.println("Stream implementation demos (RSA-PPS signing)");
546          System.out.println("=============================================");
547          //
548          // test CMS Implicit SignedDataStream
549          //
550          System.out.println("\nImplicit SignedDataStream demo [create]:\n");
551          encoding = createSignedDataStream(message, SignedDataStream.IMPLICIT);
552          // transmit data
553          System.out.println("\nImplicit SignedDataStream demo [parse]:\n");
554          received_message = getSignedDataStream(encoding, null);
555          System.out.print("\nSigned content: ");
556          System.out.println(new String(received_message));
557          
558          //
559          // test CMS Explicit SignedDataStream
560          //
561          System.out.println("\nExplicit SignedDataStream demo [create]:\n");
562          encoding = createSignedDataStream(message, SignedDataStream.EXPLICIT);
563          // transmit data
564          System.out.println("\nExplicit SignedDataStream demo [parse]:\n");
565          received_message = getSignedDataStream(encoding, message);
566          System.out.print("\nSigned content: ");
567          System.out.println(new String(received_message));
568                
569          // the non-stream implementation
570          System.out.println("\nNon-stream implementation demos (RSA-PPS signing)");
571          System.out.println("===================================================");
572       
573          //
574          // test CMS Implicit SignedData
575          //
576          System.out.println("\nImplicit CMS SignedData demo [create]:\n");
577          encoding = createSignedData(message, SignedData.IMPLICIT);
578          // transmit data
579          System.out.println("\nImplicit CMS SignedData demo [parse]:\n");
580          received_message = getSignedData(encoding, null);
581          System.out.print("\nSigned content: ");
582          System.out.println(new String(received_message));
583    
584          //
585          // test CMS Explicit SignedData
586          //
587          System.out.println("\nExplicit CMS SignedData demo [create]:\n");
588          encoding = createSignedData(message, SignedData.EXPLICIT);
589          // transmit data
590          System.out.println("\nExplicit CMS SignedData demo [parse]:\n");
591          received_message = getSignedData(encoding, message);
592          System.out.print("\nSigned content: ");
593          System.out.println(new String(received_message));
594          
595            } catch (Exception ex) {
596              ex.printStackTrace();
597              throw new RuntimeException(ex.toString());
598            }
599      }
600      
601      /**
602       * The main method.
603       */
604      public static void main(String argv[]) throws Exception {
605    
606            DemoUtil.initDemos();
607        (new PssSignedDataDemo()).start();
608        System.out.println("\nReady!");
609        DemoUtil.waitKey();
610      }
611    }