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/encryptedData/EncryptedDataDemo.java 17    12.02.25 17:58 Dbratko $
059    // $Revision: 17 $
060    //
061    
062    package demo.cms.encryptedData;
063    
064    import iaik.asn1.structures.AlgorithmID;
065    import iaik.cms.CMSException;
066    import iaik.cms.EncryptedContentInfo;
067    import iaik.cms.EncryptedContentInfoStream;
068    import iaik.cms.EncryptedData;
069    import iaik.cms.EncryptedDataStream;
070    import iaik.security.random.SecRandom;
071    import iaik.utils.Util;
072    
073    import java.io.ByteArrayInputStream;
074    import java.io.ByteArrayOutputStream;
075    import java.io.IOException;
076    import java.io.InputStream;
077    import java.security.InvalidAlgorithmParameterException;
078    import java.security.InvalidKeyException;
079    import java.security.NoSuchAlgorithmException;
080    import java.security.SecureRandom;
081    import java.security.spec.InvalidParameterSpecException;
082    
083    import demo.DemoUtil;
084    
085    /**
086     * Demonstrates the usage of class {@link iaik.cms.EncryptedDataStream} and
087     * {@link iaik.cms.EncryptedData} for encrypting data using the CMS type
088     * EncryptedData.
089     */
090    public class EncryptedDataDemo {
091    
092      // secure random number generator
093      SecureRandom random;
094    
095      /**
096       * Default constructor.
097       */
098      public EncryptedDataDemo() {
099        
100        System.out.println();
101        System.out.println("**********************************************************************************");
102        System.out.println("*                           EncryptedDataDemo demo                               *");
103        System.out.println("*        (shows the usage of the CMS EncryptedData type implementation)          *");
104        System.out.println("**********************************************************************************");
105        System.out.println();
106    
107        random = SecRandom.getDefault();
108      }
109    
110    
111      /**
112       * Creates a CMS <code>EncryptedDataStream</code> message.
113       * <p>
114       * The supplied content is PBE-encrypted using the specified password.
115       *
116       * @param message the message to be encrypted, as byte representation
117       * @param pbeAlgorithm the PBE algorithm to be used
118       * @param password the password
119       * @return the DER encoding of the <code>EncryptedData</code> object just created
120       * @throws CMSException if the <code>EncryptedData</code> object cannot
121       *                          be created
122       * @throws IOException if an I/O error occurs
123       */
124      public byte[] createEncryptedDataStream(byte[] message, AlgorithmID pbeAlgorithm, char[] password) throws CMSException, IOException {
125    
126        EncryptedDataStream encrypted_data;
127    
128        // we are testing the stream interface
129        ByteArrayInputStream is = new ByteArrayInputStream(message);
130        // create a new EncryptedData object encrypted with TripleDES CBC
131        try {
132          encrypted_data = new EncryptedDataStream(is, 2048);
133          encrypted_data.setupCipher(pbeAlgorithm, password);
134        } catch (InvalidKeyException ex) {
135          throw new CMSException("Key error: "+ex.getMessage());
136        } catch (NoSuchAlgorithmException ex) {
137          throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
138        }
139    
140        // return the EncryptedData as DER encoded byte array with block size 2048
141        ByteArrayOutputStream os = new ByteArrayOutputStream();
142        encrypted_data.writeTo(os);
143        return os.toByteArray();
144      }
145    
146      /**
147       * Decrypts the PBE-encrypted content of the given CMS <code>EncryptedData</code> object
148       * using the specified password and returns the decrypted (= original) message.
149       *
150       * @param encoding the <code>EncryptedData</code> object as DER encoded byte array
151       * @param password the password to decrypt the message
152       *
153       * @return the recovered message, as byte array
154       * @throws CMSException if the message cannot be recovered
155       * @throws IOException if an I/O error occurs
156       */
157      public byte[] getEncryptedDataStream(byte[] encoding, char[] password) throws CMSException, IOException {
158    
159        // create the EncryptpedData object from a DER encoded byte array
160        // we are testing the stream interface
161        ByteArrayInputStream is = new ByteArrayInputStream(encoding);
162        EncryptedDataStream encrypted_data = new EncryptedDataStream(is);
163    
164        System.out.println("Information about the encrypted data:");
165        EncryptedContentInfoStream eci = encrypted_data.getEncryptedContentInfo();
166        System.out.println("Content type: "+eci.getContentType().getName());
167        System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
168    
169        // decrypt the message
170        try {
171          encrypted_data.setupCipher(password);
172          InputStream decrypted = encrypted_data.getInputStream();
173          ByteArrayOutputStream os = new ByteArrayOutputStream();
174          Util.copyStream(decrypted, os, null);
175    
176          return os.toByteArray();
177    
178        } catch (InvalidKeyException ex) {
179          throw new CMSException("Key error: "+ex.getMessage());
180        } catch (NoSuchAlgorithmException ex) {
181          throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
182        } catch (InvalidAlgorithmParameterException ex) {
183          throw new CMSException("Invalid Parameters: "+ex.getMessage());
184        } catch (InvalidParameterSpecException ex) {
185          throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
186        }
187      }
188    
189      /**
190       * Creates a CMS <code>EncryptedData</code> message.
191       * <p>
192       * The supplied content is PBE-encrypted using the specified password.
193       *
194       * @param message the message to be encrypted, as byte representation
195       * @param pbeAlgorithm the PBE algorithm to be used
196       * @param password the password
197       * @return the DER encoding of the <code>EncryptedData</code> object just created
198       * @throws CMSException if the <code>EncryptedData</code> object cannot
199       *                          be created
200       * @throws IOException if an I/O error occurs
201       */
202      public byte[] createEncryptedData(byte[] message, AlgorithmID pbeAlgorithm, char[] password) throws CMSException, IOException {
203    
204        EncryptedData encrypted_data;
205    
206        try {
207          encrypted_data = new EncryptedData(message);
208          // encrypt the message
209          encrypted_data.setupCipher(pbeAlgorithm, password);
210        } catch (InvalidKeyException ex) {
211          throw new CMSException("Key error: "+ex.getMessage());
212        } catch (NoSuchAlgorithmException ex) {
213          throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
214        }
215        return encrypted_data.getEncoded();
216    
217      }
218    
219      /**
220       * Decrypts the PBE-encrypted content of the given CMS <code>EncryptedData</code> object
221       * using the specified password and returns the decrypted (= original) message.
222       *
223       * @param encoding the DER encoded <code>EncryptedData</code> object
224       * @param password the password to decrypt the message
225       *
226       * @return the recovered message, as byte array
227       * @throws CMSException if the message cannot be recovered
228       * @throws IOException if an I/O error occurs
229       */
230      public byte[] getEncryptedData(byte[] encoding, char[] password) throws CMSException, IOException {
231    
232        // create an EncryptedData from the ASN1Object
233        EncryptedData encrypted_data = new EncryptedData(new ByteArrayInputStream(encoding));
234    
235        System.out.println("Information about the encrypted data:");
236        EncryptedContentInfo eci = (EncryptedContentInfo)encrypted_data.getEncryptedContentInfo();
237        System.out.println("Content type: "+eci.getContentType().getName());
238        System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
239    
240        // decrypt the message
241        try {
242          encrypted_data.setupCipher(password);
243          return encrypted_data.getContent();
244    
245        } catch (InvalidKeyException ex) {
246          throw new CMSException("Key error: "+ex.getMessage());
247        } catch (NoSuchAlgorithmException ex) {
248          throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
249        } catch (InvalidAlgorithmParameterException ex) {
250          throw new CMSException("Invalid Parameters: "+ex.getMessage());
251        } catch (InvalidParameterSpecException ex) {
252          throw new CMSException("Content encryption algorithm not implemented: "+ex.getMessage());
253        }
254      }
255      
256    
257      /**
258       * Starts the tests.
259       */
260      public void start() {
261         // the test message
262        String m = "This is the test message.";
263        System.out.println("Test message: \""+m+"\"");
264        System.out.println();
265        byte[] message = m.getBytes();
266    
267        try {
268          byte[] encoding;
269          byte[] received_message = null;
270          System.out.println("Stream implementation demos");
271          System.out.println("===========================");
272    
273    
274          //
275          // test CMS EncryptedDataStream
276          //
277          System.out.println("\nEncryptedDataStream demo [create]:\n");
278          encoding = createEncryptedDataStream(message, (AlgorithmID)AlgorithmID.pbeWithSHAAnd3_KeyTripleDES_CBC.clone(), "password".toCharArray());
279          // transmit data
280          System.out.println("\nEncryptedDataStream demo [parse]:\n");
281          received_message = getEncryptedDataStream(encoding, "password".toCharArray());
282          System.out.print("\nContent: ");
283          System.out.println(new String(received_message));
284    
285    
286    
287          // the non-stream implementation
288          System.out.println("\nNon-stream implementation demos");
289          System.out.println("===============================");
290    
291          //
292          // test CMS EncryptedData
293          //
294          System.out.println("\nEncryptedData demo [create]:\n");
295          encoding = createEncryptedData(message, (AlgorithmID)AlgorithmID.pbeWithSHAAnd3_KeyTripleDES_CBC.clone(), "password".toCharArray());
296          // transmit data
297          System.out.println("\nEncryptedData demo [parse]:\n");
298          received_message = getEncryptedData(encoding, "password".toCharArray());
299          System.out.print("\nContent: ");
300          System.out.println(new String(received_message));
301    
302            } catch (Exception ex) {
303              ex.printStackTrace();
304              throw new RuntimeException(ex.toString());
305            }
306      }
307    
308      /**
309       * Maim method.
310       */
311      public static void main(String argv[]) throws Exception {
312    
313        DemoUtil.initDemos();
314    
315        (new EncryptedDataDemo()).start();
316        System.out.println("\nReady!");
317        DemoUtil.waitKey();
318      }
319    }