001// Copyright (C) 2002 IAIK
002// https://sic.tech/
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// This source is provided for inspection purposes and recompilation only,
011// unless specified differently in a contract with IAIK. This source has to
012// be kept in strict confidence and must not be disclosed to any third party
013// under any circumstances. Redistribution in source and binary forms, with
014// or without modification, are <not> permitted in any case!
015//
016// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
017// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
018// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
019// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
020// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
021// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
022// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
023// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
024// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
025// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
026// SUCH DAMAGE.
027//
028// $Header: /IAIK-CMS/current/src/demo/cms/pkcs11/IaikPkcs11SecurityProvider.java 11    12.02.25 17:58 Dbratko $
029//
030
031package demo.cms.pkcs11;
032
033import java.security.InvalidAlgorithmParameterException;
034import java.security.InvalidKeyException;
035import java.security.Key;
036import java.security.NoSuchAlgorithmException;
037import java.security.NoSuchProviderException;
038import java.security.PrivateKey;
039import java.security.PublicKey;
040import java.security.SecureRandom;
041import java.security.Signature;
042import java.security.SignatureException;
043import java.security.spec.AlgorithmParameterSpec;
044
045import javax.crypto.BadPaddingException;
046import javax.crypto.Cipher;
047import javax.crypto.IllegalBlockSizeException;
048import javax.crypto.NoSuchPaddingException;
049import javax.crypto.SecretKey;
050
051import iaik.asn1.structures.AlgorithmID;
052import iaik.cms.CMSAlgorithmID;
053import iaik.cms.DigestInfo;
054import iaik.cms.IaikProvider;
055import iaik.pkcs.pkcs1.RSAPssParameterSpec;
056import iaik.pkcs.pkcs11.Mechanism;
057import iaik.pkcs.pkcs11.parameters.RSAPkcsParameters;
058import iaik.pkcs.pkcs11.parameters.RSAPkcsPssParameters;
059import iaik.pkcs.pkcs11.provider.IAIKPkcs11;
060import iaik.pkcs.pkcs11.provider.keys.IAIKPKCS11Key;
061import iaik.pkcs.pkcs11.provider.keys.IAIKPKCS11PrivateKey;
062import iaik.pkcs.pkcs11.provider.signatures.PKCS11SignatureParameterSpec;
063import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
064
065
066
067/**
068 * This class implements a <code>SecurityProvider</code> for the IAIK-CMS
069 * toolkit. This <code>SecurityProvider</code> can handle
070 * <code>IAIKPKCS11Key</code> objects and is thus suitable for use with the
071 * PKCS#11 provider. The demos in this package use this class to get the
072 * IAIK-CMS library to use a PKCS#11 module instead of pure software crypto.
073 * <p>
074 * To install this security provider call:
075 * <pre>
076 * IAIKPkcs11 iaikPkcs11Provider = ...;
077 * IaikPkcs11SecurityProvider pkcs11CmsSecurityProvider = new IaikPkcs11SecurityProvider(iaikPkcs11Provider);
078 * SecurityProvider.setSecurityProvider(pkcs11CmsSecurityProvider);
079 * </pre>
080 */
081public class IaikPkcs11SecurityProvider extends IaikProvider {
082
083  /**
084   * Switch on/off debug output.
085   */
086  private final static boolean DEBUG = true;
087
088  /**
089   * The name of the security provider.
090   */
091  private final static String PROVIDER_NAME = "IAIK PKCS#11 Security Provider";
092
093  /**
094   * Reference to the installed PKCS#11 provider instance.
095   */
096  protected IAIKPkcs11 iaikPkcs11Provider_;
097
098  /**
099   * The given PKCS#11 provider instance must already be installed in the JCA 
100   * framework.
101   * 
102   * @param iaikPkcs11Provider The PKCS#11 provider instance to use in this CMS
103   *                           security provider. 
104   */
105  public IaikPkcs11SecurityProvider(IAIKPkcs11 iaikPkcs11Provider) {
106    super();
107    // providerName_ = PROVIDER_NAME;
108    iaikPkcs11Provider_ = iaikPkcs11Provider;
109  }
110
111  /**
112   * Calculates the signature value for a CMS SignerInfo over the given digest
113   * value with the given algorithm using the supplied private key.
114   * <p>
115   * Each {@link iaik.cms.SignerInfo SignerInfo} included in a CMS SignedData
116   * object may calculate the signature value differently depending on the
117   * presence of signed attributes:
118   * <p>
119   * <ul>
120   * <li>If signed attributes are present the signature is calculated over
121   *     the DER encoding of the signed attributes.
122   * <li>If signed attributes are NOT present, the signature is calculated
123   *     over the content data itsself.
124   * </ul>
125   * This method is called by class {@link iaik.cms.SignerInfo SignerInfo} for
126   * calculating the signature when no signed attributes are present. Since
127   * the data to be signed may be of arbitrary size this method expects the
128   * already hashed data to only calculate the signature value on it (for
129   * instance, by doing the digest encrypting when using RSA for signing).
130   * <p>
131   * For that reason, when writing your own SecurityProvider and overriding
132   * this method, you will need some kind of <i>RAW</i> signature (respectively
133   * digest encryption) mechanism only expecting the already hashed data (e.g.
134   * a "RawDSA" signature engine when using DSA repectively a Cipher engine
135   * when using RSA).
136   * <p>
137   * If you want to override this method for use with smartcards, please be sure
138   * that your smartcard is able to do the signature (respectively digest
139   * encryption) operation only. However, if your smartcard requires to supply
140   * the whole data for doing the hash calcualtion itself, you may ensure that
141   * your {@link iaik.cms.SignerInfo SignerInfo} contains signed attributes
142   * and override method {@link #calculateSignatureFromSignedAttributes
143   * calculateSignatureFromSignedAttributes} for calculating the signature over
144   * the DER encoding of the signed attributes (thereby doing the hash
145   * computation, too).
146   *
147   * @param signatureAlgorithm signatureAlgorithm the signature algorithm to be
148   *        used, e.g. rsaEncryption, DSA
149   * @param digestAlgorithm the digest algorithm used for hash computation (e.g.
150   *        SHA-1 or MD5); may be necessary for some signature schemes (e.g.
151   *        to be included as a DigestInfo in a PKCS#1 RSA signature)
152   * @param privateKey the private key of the signer (i.e. the one supplied when
153   *        creating a {@link iaik.cms.SignerInfo SignerInfo} object; may be
154   *        some kind of "dummy" key when used for smartcards
155   * @param digest the digest value over which the signature shall be calculated
156   *
157   * @return the signature value calculated from the given digest value
158   *
159   * @throws NoSuchAlgorithmException if any of the required algorithms is not supported
160   * @throws InvalidKeyException if the key is not valid
161   * @throws SignatureException if signature verification fails because of some crypto related error
162   */
163  public byte[] calculateSignatureFromHash(AlgorithmID signatureAlgorithm,
164    AlgorithmID digestAlgorithm, PrivateKey privateKey, byte[] digest)
165      throws NoSuchAlgorithmException, InvalidKeyException, SignatureException
166  {
167    byte[] signatureValue;
168
169    // we handle PKCS#11 keys in a special way, but we forward other keys to the default implementation
170    if (privateKey instanceof IAIKPKCS11PrivateKey) {
171      IAIKPkcs11 iaikPkcs11KeyProvider = ((IAIKPKCS11PrivateKey) privateKey).getTokenManager().getProvider();
172
173      String algorithmName = privateKey.getAlgorithm();
174
175      Signature signatureEngine;
176      byte[] dataToBeSigned = digest;
177      try {
178        if (algorithmName.equals("RSA")) {
179          if (signatureAlgorithm.equals(CMSAlgorithmID.rsassaPss)) {   
180            signatureEngine = Signature.getInstance("RawRSA/PSS", iaikPkcs11KeyProvider.getName());
181            PKCS11SignatureParameterSpec params = generateRSAPssParameters(digestAlgorithm, signatureAlgorithm);
182            try {
183              signatureEngine.setParameter(params);
184            } catch (InvalidAlgorithmParameterException e) {
185              throw new SignatureException("Error setting RSA-PSS algorithm parameters: " + e.toString());
186            }
187          } else {
188            DigestInfo digestInfo = new DigestInfo(digestAlgorithm, digest);
189            dataToBeSigned = digestInfo.toByteArray();
190            signatureEngine = Signature.getInstance("RawRSA/PKCS1", iaikPkcs11KeyProvider.getName());
191          }  
192        } else if (algorithmName.equals("DSA")) {
193          signatureEngine = Signature.getInstance("RawDSA", iaikPkcs11KeyProvider.getName());
194        } else if ((algorithmName.equals("EC")) || (algorithmName.equals("ECDSA"))) {
195          signatureEngine = Signature.getInstance("RawECDSA", iaikPkcs11KeyProvider.getName());
196        } else {
197          throw new NoSuchAlgorithmException(
198            "Unable to calculate signature with signature algorithm: " + signatureAlgorithm);
199        }
200        
201      } catch (NoSuchProviderException ex) {
202        throw new NoSuchAlgorithmException("The PKCS#11 provider has not been installed corerctly: " + ex);
203      }
204      signatureEngine.initSign(privateKey);
205      signatureEngine.update(dataToBeSigned);
206      signatureValue = signatureEngine.sign();
207    } else {
208      signatureValue = super.calculateSignatureFromHash(signatureAlgorithm, digestAlgorithm, privateKey, digest);
209    }
210
211    return signatureValue ;
212  }
213  
214  /**
215   * Calculates the signature value for a CMS SignerInfo over the given signed 
216   * attributes with the given algorithm using the supplied private key.
217   * <p>
218   * Each {@link iaik.cms.SignerInfo SignerInfo} included in a CMS SignedData
219   * object may calculate the signature value differently depending on the
220   * presence of signed attributes:
221   * <p>
222   * <ul>
223   * <li>If signed attributes are present the signature is calculated over
224   *     the DER encoding of the signed attributes. 
225   * <li>If signed attributes are NOT present, the signature is calculated
226   *     over the content data itsself.
227   * </ul>
228   * This method is called by class {@link iaik.cms.SignerInfo SignerInfo} for
229   * calculating the signature when signed attributes are present. 
230   * <p>
231   * When writing your own SecurityProvider and overriding
232   * this method, be aware that only the -- yet NOT hashed -- DER encoding of
233   * the signed attributes is supplied to this method. For that reason this
234   * method can be overriden for use with smartcards requiring to do the 
235   * digest calculation theirselves: ensure that your {@link iaik.cms.SignerInfo
236   * SignerInfo} contains signed attributes and override this method in a way
237   * to pass the given DER encoding of the signed attributes to your smartcard
238   * for doing the signature (and digest) calculation.
239   * <p>
240   * Since this method requires to calculate the digest value over the DER encoded
241   * signed attributes as part of the signature calculation, it uses a 
242   * ordinary JCA Signature engine.
243   *
244   * @param signatureAlgorithm signatureAlgorithm the signature algorithm to be
245   *        used, e.g. rsaEncryption, DSA
246   * @param digestAlgorithm the digest algorithm to be used for hash computation (e.g.
247   *        SHA-1,..., SHA-512); may be necessary for some signature schemes (e.g.
248   *        to be included as a DigestInfo in a PKCS#1 RSA signature)
249   * @param privateKey the private key of the signer (i.e. the one supplied when
250   *        creating a {@link iaik.cms.SignerInfo SignerInfo} object; may be
251   *        some kind of "dummy" key when used for smartcards
252   * @param signedAttributes the DER encoding of the signed attributes over which 
253   *        the signature shall be calculated
254   *
255   * @return the signature value calculated from the given DER encoded signed
256   *         attributes
257   *
258   * @throws NoSuchAlgorithmException if no Signature engine is available for the requested algorithm
259   * @throws InvalidKeyException if the key is not valid
260   * @throws SignatureException if signature calculation fails
261   */
262  public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm, 
263    AlgorithmID digestAlgorithm, PrivateKey privateKey, byte[] signedAttributes) 
264    throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
265      
266    byte[] digest = getHash(digestAlgorithm, signedAttributes);
267    return calculateSignatureFromHash(signatureAlgorithm, digestAlgorithm, privateKey, digest);
268
269  }  
270
271  /**
272   * This method returns the desired Signature object which uses the PKCS#11
273   * provider if the key is a PKCS#11 key.
274   *
275   * If the mode parameter is <CODE>SIGNATURE_SIGN</CODE> or 
276   * <CODE>SIGNATURE_VERIFY</CODE> the signature object has to be
277   * initialized with the provided key in the respective mode.
278   *
279   * @param algorithm the name of the Signature algorithm
280   * @param mode the mode indicating if the engine has to be initialized
281   * @param key the key for initializing the Signature engine
282   *
283   * @return the (if requested initialized) Signature engine
284   *
285   * @throws InvalidKeyException if the key is not valid 
286   * @throws NoSuchAlgorithmException if no Signature engine is
287   *            available for the requested algorithm
288   */
289  public Signature getSignature(String algorithm, int mode, Key key) 
290    throws InvalidKeyException, NoSuchAlgorithmException {
291        
292    Signature signature;
293    
294    // for PKCS#11 keys we use the PKCS#11 provider, for other keys we use the default implementation
295    if (key instanceof IAIKPKCS11Key) {
296      try {
297        signature = Signature.getInstance(algorithm, iaikPkcs11Provider_.getName());
298      } catch (NoSuchProviderException e) {
299        throw new NoSuchAlgorithmException("PKCS#11 Provider has not been installed correctly " + e.toString());
300      }  
301      if (mode == SIGNATURE_SIGN) {
302        signature.initSign((PrivateKey)key);
303      } else if (mode == SIGNATURE_VERIFY) {
304        signature.initVerify((PublicKey)key);
305      } // do nothing for SIGNATURE_NONE
306    } else {
307      signature = super.getSignature(algorithm, mode, key);  
308    }
309    
310    return signature ;
311  }
312  
313  /**
314   * This method returns the desired Signature object.
315   *
316   * If the mode parameter is <CODE>SIGNATURE_SIGN</CODE> or 
317   * <CODE>SIGNATURE_VERIFY</CODE> the signature object is to be
318   * initialized with the provided key in the respective mode.
319   * If algorithm parameters are specified they are set for the
320   * Signature engine.
321   *
322   * @param algorithm the AlgorithmID of the Signature algorithm
323   * @param mode the mode indicating if the engine has to be initialized
324   * @param key the key for initializing the Signature engine
325   * @param paramSpec any parameters to be set for the Signature engine, if not <code>null</code>
326   *
327   * @return the (if requested initialized) Signature engine
328   *
329   * @throws InvalidKeyException if the key is not valid 
330   * @throws NoSuchAlgorithmException if no Signature engine is
331   *            available for the requested algorithm
332   */
333  public Signature getSignature(AlgorithmID algorithm, 
334                                int mode, 
335                                Key key,
336                                AlgorithmParameterSpec paramSpec) 
337   throws InvalidKeyException, NoSuchAlgorithmException {
338    
339    Signature signature;
340    
341    // for PKCS#11 keys we use the PKCS#11 provider, for other keys we use the default implementation
342    if (key instanceof IAIKPKCS11Key) {
343     
344      signature = algorithm.getSignatureInstance(iaikPkcs11Provider_.getName());
345        
346      if (mode == SIGNATURE_SIGN) {
347        signature.initSign((PrivateKey)key);
348      } else if (mode == SIGNATURE_VERIFY) {
349        signature.initVerify((PublicKey)key);
350      } // do nothing for SIGNATURE_NONE
351    } else {
352      signature = super.getSignature(algorithm, mode, key, paramSpec);  
353    }
354    if (paramSpec != null) {
355      setSignatureParameters(signature, paramSpec);
356    }
357    return signature ;
358    
359  }
360  
361  /**
362   * Calculates RSA-PSS parameters for the given digest algorithm
363   * 
364   * @param digestAlgorithm the digest algorithm
365   * @param signatureAlgorithm the signature algorithm
366   * 
367   * @return the generated parameters
368   * 
369   * @throws NoSuchAlgorithmException if no parameters for the given digest algorithms are available
370   */
371   private static PKCS11SignatureParameterSpec generateRSAPssParameters(
372       AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm) 
373     throws NoSuchAlgorithmException {
374     
375     
376     Mechanism hashAlgorithm;
377     long messageGenerationFunctionType;
378     int saltLength;
379     if (digestAlgorithm.equals(AlgorithmID.sha1)) {
380       hashAlgorithm = Mechanism.get(PKCS11Constants.CKM_SHA_1);
381       messageGenerationFunctionType = RSAPkcsParameters.MessageGenerationFunctionType.SHA1;
382       saltLength = 20;
383     } else if (digestAlgorithm.equals(AlgorithmID.sha256)) {
384       hashAlgorithm = Mechanism.get(PKCS11Constants.CKM_SHA256);
385       messageGenerationFunctionType = RSAPkcsParameters.MessageGenerationFunctionType.SHA256;
386       saltLength = 32;
387     } else if (digestAlgorithm.equals(AlgorithmID.sha384)) {
388       hashAlgorithm = Mechanism.get(PKCS11Constants.CKM_SHA384);
389       messageGenerationFunctionType = RSAPkcsParameters.MessageGenerationFunctionType.SHA384;
390       saltLength = 48;
391     } else if (digestAlgorithm.equals(AlgorithmID.sha512)) {
392       hashAlgorithm = Mechanism.get(PKCS11Constants.CKM_SHA512);
393       messageGenerationFunctionType = RSAPkcsParameters.MessageGenerationFunctionType.SHA512;
394       saltLength = 64;
395     } else {
396       throw new NoSuchAlgorithmException(
397           "Cannot create RSA-PSS parameters for " + digestAlgorithm.getName()
398               + " digest algorithm!");
399     }
400     RSAPkcsPssParameters parameters = new RSAPkcsPssParameters(
401         hashAlgorithm, messageGenerationFunctionType, saltLength);
402     PKCS11SignatureParameterSpec params = new PKCS11SignatureParameterSpec(
403         parameters);
404     
405     // set signature algorithm parameters
406     AlgorithmID mgf1 = (AlgorithmID)AlgorithmID.mgf1.clone(); 
407     mgf1.setParameter(digestAlgorithm.toASN1Object());
408     RSAPssParameterSpec pssParamSpec = new RSAPssParameterSpec(digestAlgorithm, 
409         mgf1, saltLength);
410     try {
411       signatureAlgorithm.setAlgorithmParameterSpec(pssParamSpec);
412     } catch (InvalidAlgorithmParameterException e) {
413       throw new NoSuchAlgorithmException(e.toString());
414     }
415     return params;
416   }
417 
418  /**
419   * Decrypts the given encrypted content encryption key for a {@link 
420   * iaik.cms.KeyTransRecipientInfo KeyTransRecipientInfo}.
421   * <p>
422   * CMS <code>EnvelopedData</code> uses the {@link 
423   * iaik.cms.KeyTransRecipientInfo KeyTransRecipientInfo} type for
424   * encrypting the secret content encryption key with the public key of
425   * the recipient. Currently in general RSA PKCS#1v1.5 is used for key
426   * transport. If rsaEncryption is requested as key encryption algorithm
427   * this method uses a RSA Cipher ("RSA/ECB/PKCS1Padding/Encrypt") for
428   * decrypting the encrypted content encryption key with the supplied 
429   * private key of the recipient. If another algorithm than RSA is requested,
430   * this method throws a NoSuchAlgorithmException. An application wishing to
431   * support another algorithm may override this method.
432   *
433   * @param encryptedKey the encrypted content encryption key to be decrypted
434   * @param kea the key encryption alglorithm to be used, e.g. rsaEncryption
435   * @param recipientKey the private key of the recipient to be used for decrypting
436   *                     the encrypted content encryption key
437   * @param cekAlgorithmName the name of the content encryption key (e.g. "DES") to be set for the
438   *                         SecretKey object created by this method
439   *
440   * @return the decrypted content encryption key
441   *
442   * @throws NoSuchAlgorithmException if the requested algorithm is not available
443   * @throws InvalidKeyException if the decryption key is not valid
444   * @throws NoSuchPaddingException if the required padding scheme is not supported
445   * @throws BadPaddingException if an padding error occurs
446   */
447  public SecretKey decryptKey(byte[] encryptedKey, AlgorithmID kea, PrivateKey recipientKey, String cekAlgorithmName) 
448    throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException 
449  {
450    SecretKey decryptedSymmetricKey;
451
452    // we handle PKCS#11 keys in a special way, but we forward other keys to the default implementation
453    if (recipientKey instanceof IAIKPKCS11PrivateKey) {
454      IAIKPkcs11 iaikPkcs11KeyProvider = ((IAIKPKCS11PrivateKey) recipientKey).getTokenManager().getProvider();
455      String algorithmImplementationName = kea.getImplementationName();
456
457      try {
458        Cipher cipher = Cipher.getInstance(algorithmImplementationName, iaikPkcs11KeyProvider.getName());
459        cipher.init(Cipher.DECRYPT_MODE, recipientKey, (AlgorithmParameterSpec) null, (SecureRandom) null);
460        byte[] cek = cipher.doFinal(encryptedKey);
461        decryptedSymmetricKey = new iaik.security.cipher.SecretKey(cek, cekAlgorithmName);
462        
463      } catch (NoSuchProviderException ex) {
464        throw new NoSuchAlgorithmException("The PKCS#11 provider has not been installed corerctly: " + ex);
465      } catch (InvalidAlgorithmParameterException ex) {
466        throw new NoSuchAlgorithmException("Error initializing the cipher: " + ex);
467      } catch (IllegalBlockSizeException ex) {
468        throw new NoSuchAlgorithmException("Error during cipher operation: " + ex);
469      }
470    } else {
471      decryptedSymmetricKey = super.decryptKey(encryptedKey, kea, recipientKey, cekAlgorithmName);
472    }
473
474    return decryptedSymmetricKey ;
475  }
476
477  /**
478   * Decrypts the given encrypted content encryption key for a {@link 
479   * iaik.cms.KeyTransRecipientInfo KeyTransRecipientInfo}.
480   * <p>
481   * CMS <code>EnvelopedData</code> uses the {@link 
482   * iaik.cms.KeyTransRecipientInfo KeyTransRecipientInfo} type for
483   * encrypting the secret content encryption key with the public key of
484   * the recipient. Currently in general RSA PKCS#1v1.5 is used for key
485   * transport. If rsaEncryption is requested as key encryption algorithm
486   * this method uses a RSA Cipher ("RSA/ECB/PKCS1Padding/Encrypt") for
487   * decrypting the encrypted content encryption key with the supplied 
488   * private key of the recipient. If another algorithm than RSA is requested,
489   * this method throws a NoSuchAlgorithmException. An application wishing to
490   * support another algorithm may override this method.
491   *
492   * @param encryptedKey the encrypted content encryption key to be decrypted
493   * @param kea the key encryption alglorithm to be used, e.g. rsaEncryption
494   * @param recipientKey the private key of the recipient to be used for decrypting
495   *                     the encrypted content encryption key
496   *
497   * @return the decrypted content encryption key, the algorithm name will be set to "RAW"
498   *
499   * @throws NoSuchAlgorithmException if the requested algorithm is not available
500   * @throws InvalidKeyException if the decryption key is not valid
501   * @throws NoSuchPaddingException if the required padding scheme is not supported
502   * @throws BadPaddingException if an padding error occurs
503   */
504// only needed for old CMS versions
505//  public SecretKey decryptKey(byte[] encryptedKey, AlgorithmID kea, PrivateKey recipientKey) 
506//    throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException 
507//  {
508//    return decryptKey(encryptedKey, kea, recipientKey, "RAW"); 
509//  }
510    
511}