266. EPMO Open Source Coordination Office Redaction File Detail Report

Produced by Araxis Merge on 9/25/2018 2:13:24 PM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

266.1 Files compared

# Location File Last Modified
1 build 3.zip\build 3\MHLTH_YS_137_Source\JavaScript\resources\javaJDF-1.8.0\src\sun\security\pkcs12 PKCS12KeyStore.java Mon Jan 22 14:46:54 2018 UTC
2 build 3.zip\build 3\MHLTH_YS_137_Source\JavaScript\resources\javaJDF-1.8.0\src\sun\security\pkcs12 PKCS12KeyStore.java Wed Sep 12 17:53:41 2018 UTC

266.2 Comparison summary

Description Between
Files 1 and 2
Text Blocks Lines
Unchanged 36 4704
Changed 35 100
Inserted 0 0
Removed 0 0

266.3 Comparison options

Whitespace
Character case Differences in character case are significant
Line endings Differences in line endings (CR and LF characters) are ignored
CR/LF characters Not shown in the comparison detail

266.4 Active regular expressions

No regular expressions were active.

266.5 Comparison detail

  1   /*
  2    * Copyrig ht (c) 199 9, 2017, O racle and/ or its aff iliates. A ll rights  reserved.
  3    * DO NOT  ALTER OR R EMOVE COPY RIGHT NOTI CES OR THI S FILE HEA DER.
  4    *
  5    * This co de is free  software;  you can r edistribut e it and/o r modify i t
  6    * under t he terms o f the GNU  General Pu blic Licen se version  2 only, a s
  7    * publish ed by the  Free Softw are Founda tion.  Ora cle design ates this
  8    * particu lar file a s subject  to the "Cl asspath" e xception a s provided
  9    * by Orac le in the  LICENSE fi le that ac companied  this code.
  10    *
  11    * This co de is dist ributed in  the hope  that it wi ll be usef ul, but WI THOUT
  12    * ANY WAR RANTY; wit hout even  the implie d warranty  of MERCHA NTABILITY  or
  13    * FITNESS  FOR A PAR TICULAR PU RPOSE.  Se e the GNU  General Pu blic Licen se
  14    * version  2 for mor e details  (a copy is  included  in the LIC ENSE file  that
  15    * accompa nied this  code).
  16    *
  17    * You sho uld have r eceived a  copy of th e GNU Gene ral Public  License v ersion
  18    * 2 along  with this  work; if  not, write  to the Fr ee Softwar e Foundati on,
  19    * Inc., 5 1 Franklin  St, Fifth  Floor, Bo ston, MA 0 2110-1301  USA.
  20    *
  21    * Please  contact Or acle, 500  Oracle Par kway, Redw ood Shores , CA 94065  USA
  22    * or visi t www.orac le.com if  you need a dditional  informatio n or have  any
  23    * questio ns.
  24    */
  25  
  26   package su n.security .pkcs12;
  27  
  28   import jav a.io.*;
  29   import jav a.security .AccessCon troller;
  30   import jav a.security .MessageDi gest;
  31   import jav a.security .NoSuchAlg orithmExce ption;
  32   import jav a.security .Key;
  33   import jav a.security .KeyFactor y;
  34   import jav a.security .KeyStore;
  35   import jav a.security .KeyStoreS pi;
  36   import jav a.security .KeyStoreE xception;
  37   import jav a.security .PKCS12Att ribute;
  38   import jav a.security .PrivateKe y;
  39   import jav a.security .Privilege dAction;
  40   import jav a.security .Unrecover ableEntryE xception;
  41   import jav a.security .Unrecover ableKeyExc eption;
  42   import jav a.security .SecureRan dom;
  43   import jav a.security .Security;
  44   import jav a.security .cert.Cert ificate;
  45   import jav a.security .cert.Cert ificateFac tory;
  46   import jav a.security .cert.X509 Certificat e;
  47   import jav a.security .cert.Cert ificateExc eption;
  48   import jav a.security .spec.Algo rithmParam eterSpec;
  49   import jav a.security .spec.Inva lidParamet erSpecExce ption;
  50   import jav a.security .spec.KeyS pec;
  51   import jav a.security .spec.PKCS 8EncodedKe ySpec;
  52   import jav a.util.*;
  53  
  54   import jav a.security .Algorithm Parameters ;
  55   import jav a.security .InvalidAl gorithmPar ameterExce ption;
  56   import jav ax.crypto. spec.PBEPa rameterSpe c;
  57   import jav ax.crypto. spec.PBEKe ySpec;
  58   import jav ax.crypto. spec.Secre tKeySpec;
  59   import jav ax.crypto. SecretKeyF actory;
  60   import jav ax.crypto. SecretKey;
  61   import jav ax.crypto. Cipher;
  62   import jav ax.crypto. Mac;
  63   import jav ax.securit y.auth.Des troyFailed Exception;
  64   import jav ax.securit y.auth.x50 0.X500Prin cipal;
  65  
  66   import sun .security. util.Debug ;
  67   import sun .security. util.DerIn putStream;
  68   import sun .security. util.DerOu tputStream ;
  69   import sun .security. util.DerVa lue;
  70   import sun .security. util.Objec tIdentifie r;
  71   import sun .security. pkcs.Conte ntInfo;
  72   import sun .security. x509.Algor ithmId;
  73   import sun .security. pkcs.Encry ptedPrivat eKeyInfo;
  74  
  75  
  76   /**
  77    * This cl ass provid es the key store impl ementation  referred  to as "PKC S12".
  78    * Impleme nts the PK CS#12 PFX  protected  using the  Password p rivacy mod e.
  79    * The con tents are  protected  using Pass word integ rity mode.
  80    *
  81    * Current ly we supp ort follow ing PBE al gorithms:
  82    *  - pbeW ithSHAAnd3 KeyTripleD ESCBC to e ncrypt pri vate keys
  83    *  - pbeW ithSHAAnd4 0BitRC2CBC  to encryp t certific ates
  84    *
  85    * Support ed encrypt ion of var ious imple mentations  :
  86    *
  87    * Softwar e and mode .     Cert ificate en cryption   Private ke y encrypti on
  88    * ------- ---------- ---------- ---------- ---------- ---------- ---------- --
  89    * MSIE4 ( domestic              40 bit RC2 .             40 bit  RC2
  90    * and xpo rt version s)
  91    * PKCS#12  export.
  92    *
  93    * MSIE4,  5 (domesti c          40 bit RC2 ,             40 bit  RC2,
  94    * and exp ort versio ns)        3 key trip le DES        3 key t riple DES
  95    * PKCS#12  import.
  96    *
  97    * MSIE5                         40 bit RC2               3 key t riple DES,
  98    * PKCS#12  export.                                       with SH A1 (168 bi ts)
  99    *
  100    * Netscap e Communic ator       40 bit RC2               3 key t riple DES,
  101    * (domest ic and exp ort                                 with SH A1 (168 bi ts)
  102    * version s) PKCS#12  export
  103    *
  104    * Netscap e Communic ator       40 bit cip hers only     All.
  105    * (export  version)
  106    * PKCS#12  import.
  107    *
  108    * Netscap e Communic ator       All.                     All.
  109    * (domest ic or fort ified
  110    * version ) PKCS#12  import.
  111    *
  112    * OpenSSL  PKCS#12 c ode.       All.                     All.
  113    * ------- ---------- ---------- ---------- ---------- ---------- ---------- --
  114    *
  115    * NOTE: P KCS12 KeyS tore suppo rts Privat eKeyEntry  and Truste dCertficat eEntry.
  116    * PKCS#12  is mainly  used to d eliver pri vate keys  with their  associate d
  117    * certifi cate chain  and alias es. In a P KCS12 keys tore, entr ies are
  118    * identif ied by the  alias, an d a localK eyId is re quired to  match the
  119    * private  key with  the certif icate. Tru sted certi ficate ent ries are i dentified
  120    * by the  presence o f an trust edKeyUsage  attribute .
  121    *
  122    * @author  Seema Mal kani
  123    * @author  Jeff Nise wanger
  124    * @author  Jan Luehe
  125    *
  126    * @see Ke yProtector
  127    * @see ja va.securit y.KeyStore Spi
  128    * @see Ke yTool
  129    *
  130    *
  131    */
  132   public fin al class P KCS12KeySt ore extend s KeyStore Spi {
  133  
  134       public  static fi nal int VE RSION_3 =  3;
  135  
  136       privat e static f inal Strin g[] KEY_PR OTECTION_A LGORITHM =  {
  137           "k eystore.pk cs12.keyPr otectionAl gorithm",
  138           "k eystore.PK CS12.keyPr otectionAl gorithm"
  139       };
  140  
  141       privat e static f inal int M AX_ITERATI ON_COUNT =  5000000;
  142       privat e static f inal int P BE_ITERATI ON_COUNT =  50000; //  default
  143       privat e static f inal int M AC_ITERATI ON_COUNT =  100000; / / default
  144       privat e static f inal int S ALT_LEN =  20;
  145  
  146       // fri endlyName,  localKeyI d, trusted KeyUsage
  147       privat e static f inal Strin g[] CORE_A TTRIBUTES  = {
  148           "1 .2.840.113 549.1.9.20 ",
  149           "1 .2.840.113 549.1.9.21 ",
  150           "2 .16.840.1. 113894.746 875.1.1"
  151       };
  152  
  153       privat e static f inal Debug  debug = D ebug.getIn stance("pk cs12");
  154  
  155       privat e static f inal int k eyBag[]  =  {1, 2, 84 0, 113549,  1, 12, 10 , 1, 2};
  156       privat e static f inal int c ertBag[] =  {1, 2, 84 0, 113549,  1, 12, 10 , 1, 3};
  157         private st atic final  int  PW      Bag[] = {1 , 2, 840,  113549, 1,  12, 10, 1 , 5};
  158  
  159       privat e static f inal int p kcs9Name[]   = {1, 2,  840, 1135 49, 1, 9,  20};
  160       privat e static f inal int p kcs9KeyId[ ] = {1, 2,  840, 1135 49, 1, 9,  21};
  161  
  162       privat e static f inal int p kcs9certTy pe[] = {1,  2, 840, 1 13549, 1,  9, 22, 1};
  163  
  164       privat e static f inal int p beWithSHAA nd40BitRC2 CBC[] =
  165                                               {1, 2, 840 , 113549,  1, 12, 1,  6};
  166       privat e static f inal int p beWithSHAA nd3KeyTrip leDESCBC[]  =
  167                                               {1, 2, 840 , 113549,  1, 12, 1,  3};
  168       privat e static f inal int p bes2[] = { 1, 2, 840,  113549, 1 , 5, 13};
  169       // TOD O: tempora ry Oracle  OID
  170       /*
  171        * { j oint-iso-i tu-t(2) co untry(16)  us(840) or ganization (1) oracle (113894)
  172        *   j dk(746875)  crypto(1)  id-at-tru stedKeyUsa ge(1) }
  173        */
  174       privat e static f inal int T rustedKeyU sage[] =
  175                                               {2, 16, 84 0, 1, 1138 94, 746875 , 1, 1};
  176       privat e static f inal int A nyExtended KeyUsage[]  = {2, 5,  29, 37, 0} ;
  177  
  178       privat e static O bjectIdent ifier PKCS 8ShroudedK eyBag_OID;
  179       privat e static O bjectIdent ifier Cert Bag_OID;
  180       privat e static O bjectIdent ifier Secr etBag_OID;
  181       privat e static O bjectIdent ifier PKCS 9FriendlyN ame_OID;
  182       privat e static O bjectIdent ifier PKCS 9LocalKeyI d_OID;
  183       privat e static O bjectIdent ifier PKCS 9CertType_ OID;
  184       privat e static O bjectIdent ifier pbeW ithSHAAnd4 0BitRC2CBC _OID;
  185       privat e static O bjectIdent ifier pbeW ithSHAAnd3 KeyTripleD ESCBC_OID;
  186       privat e static O bjectIdent ifier pbes 2_OID;
  187       privat e static O bjectIdent ifier Trus tedKeyUsag e_OID;
  188       privat e static O bjectIdent ifier[] An yUsage;
  189  
  190       privat e int coun ter = 0;
  191  
  192       // pri vate key c ount
  193       // Not e: This is  a workaro und to all ow null lo calKeyID a ttribute
  194       // in  pkcs12 wit h one priv ate key en try and as sociated c ert-chain
  195       privat e int priv ateKeyCoun t = 0;
  196  
  197         //  PW        key count
  198         private in PW      KeyCount =  0;
  199  
  200       // cer tificate c ount
  201       privat e int cert ificateCou nt = 0;
  202  
  203       // the  source of  randomnes s
  204       privat e SecureRa ndom rando m;
  205  
  206       static  {
  207           tr y {
  208                PKCS8Shr oudedKeyBa g_OID = ne w ObjectId entifier(k eyBag);
  209                CertBag_ OID = new  ObjectIden tifier(cer tBag);
  210                  SecretBag_ OID = new  ObjectIden tifier( PW      Bag);
  211                PKCS9Fri endlyName_ OID = new  ObjectIden tifier(pkc s9Name);
  212                PKCS9Loc alKeyId_OI D = new Ob jectIdenti fier(pkcs9 KeyId);
  213                PKCS9Cer tType_OID  = new Obje ctIdentifi er(pkcs9ce rtType);
  214                pbeWithS HAAnd40Bit RC2CBC_OID  =
  215                             new Ob jectIdenti fier(pbeWi thSHAAnd40 BitRC2CBC) ;
  216                pbeWithS HAAnd3KeyT ripleDESCB C_OID =
  217                             new Ob jectIdenti fier(pbeWi thSHAAnd3K eyTripleDE SCBC);
  218                pbes2_OI D = new Ob jectIdenti fier(pbes2 );
  219                TrustedK eyUsage_OI D = new Ob jectIdenti fier(Trust edKeyUsage );
  220                AnyUsage  = new Obj ectIdentif ier[]{
  221                    new  ObjectIden tifier(Any ExtendedKe yUsage)};
  222           }  catch (IOE xception i oe) {
  223                // shoul d not happ en
  224           }
  225       }
  226  
  227       // A k eystore en try and as sociated a ttributes
  228       privat e static c lass Entry  {
  229           Da te date; / / the crea tion date  of this en try
  230           St ring alias ;
  231           by te[] keyId ;
  232           Se t<KeyStore .Entry.Att ribute> at tributes;
  233       }
  234  
  235       // A k ey entry
  236       privat e static c lass KeyEn try extend s Entry {
  237       }
  238  
  239       // A p rivate key  entry and  its suppo rting cert ificate ch ain
  240       privat e static c lass Priva teKeyEntry  extends K eyEntry {
  241           by te[] prote ctedPrivKe y;
  242           Ce rtificate  chain[];
  243       };
  244  
  245         // A  PW        key
  246       privat e static c lass Secre tKeyEntry  extends Ke yEntry {
  247           by te[] prote ctedSecret Key;
  248       };
  249  
  250       // A c ertificate  entry
  251       privat e static c lass CertE ntry exten ds Entry {
  252           fi nal X509Ce rtificate  cert;
  253           Ob jectIdenti fier[] tru stedKeyUsa ge;
  254  
  255           Ce rtEntry(X5 09Certific ate cert,  byte[] key Id, String  alias) {
  256                this(cer t, keyId,  alias, nul l, null);
  257           }
  258  
  259           Ce rtEntry(X5 09Certific ate cert,  byte[] key Id, String  alias,
  260                    Obje ctIdentifi er[] trust edKeyUsage ,
  261                    Set< ? extends  KeyStore.E ntry.Attri bute> attr ibutes) {
  262                this.dat e = new Da te();
  263                this.cer t = cert;
  264                this.key Id = keyId ;
  265                this.ali as = alias ;
  266                this.tru stedKeyUsa ge = trust edKeyUsage ;
  267                this.att ributes =  new HashSe t<>();
  268                if (attr ibutes !=  null) {
  269                    this .attribute s.addAll(a ttributes) ;
  270                }
  271           }
  272       }
  273  
  274       /**
  275        * Pri vate keys  and certif icates are  stored in  a map.
  276        * Map  entries a re keyed b y alias na mes.
  277        */
  278       privat e Map<Stri ng, Entry>  entries =
  279           Co llections. synchroniz edMap(new  LinkedHash Map<String , Entry>() );
  280  
  281       privat e ArrayLis t<KeyEntry > keyList  = new Arra yList<KeyE ntry>();
  282       privat e LinkedHa shMap<X500 Principal,  X509Certi ficate> ce rtsMap =
  283                new Link edHashMap< X500Princi pal, X509C ertificate >();
  284       privat e ArrayLis t<CertEntr y> certEnt ries = new  ArrayList <CertEntry >();
  285  
  286       /**
  287        * Ret urns the k ey associa ted with t he given a lias, usin g the give n
  288        * pas sword to r ecover it.
  289        *
  290        * @pa ram alias  the alias  name
  291        * @pa ram passwo rd the pas sword for  recovering  the key
  292        *
  293        * @re turn the r equested k ey, or nul l if the g iven alias  does not  exist
  294        * or  does not i dentify a  <i>key ent ry</i>.
  295        *
  296        * @ex ception No SuchAlgori thmExcepti on if the  algorithm  for recove ring the
  297        * key  cannot be  found
  298        * @ex ception Un recoverabl eKeyExcept ion if the  key canno t be recov ered
  299        * (e. g., the gi ven passwo rd is wron g).
  300        */
  301       public  Key engin eGetKey(St ring alias , char[] p assword)
  302           th rows NoSuc hAlgorithm Exception,  Unrecover ableKeyExc eption
  303       {
  304           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  305           Ke y key = nu ll;
  306  
  307           if  (entry ==  null || ( !(entry in stanceof K eyEntry)))  {
  308                return n ull;
  309           }
  310  
  311             // get the  encoded p rivate key  or  PW        key
  312           by te[] encrB ytes = nul l;
  313           if  (entry in stanceof P rivateKeyE ntry) {
  314                encrByte s = ((Priv ateKeyEntr y) entry). protectedP rivKey;
  315           }  else if (e ntry insta nceof Secr etKeyEntry ) {
  316                encrByte s = ((Secr etKeyEntry ) entry).p rotectedSe cretKey;
  317           }  else {
  318                throw ne w Unrecove rableKeyEx ception("E rror locat ing key");
  319           }
  320  
  321           by te[] encry ptedKey;
  322           Al gorithmPar ameters al gParams;
  323           Ob jectIdenti fier algOi d;
  324  
  325           tr y {
  326                // get t he encrypt ed private  key
  327                Encrypte dPrivateKe yInfo encr Info =
  328                             new En cryptedPri vateKeyInf o(encrByte s);
  329                encrypte dKey = enc rInfo.getE ncryptedDa ta();
  330  
  331                // parse  Algorithm  parameter s
  332                DerValue  val = new  DerValue( encrInfo.g etAlgorith m().encode ());
  333                DerInput Stream in  = val.toDe rInputStre am();
  334                algOid =  in.getOID ();
  335                algParam s = parseA lgParamete rs(algOid,  in);
  336  
  337           }  catch (IOE xception i oe) {
  338                Unrecove rableKeyEx ception uk e =
  339                    new  Unrecovera bleKeyExce ption("Pri vate key n ot stored  as "
  340                                       + "PKCS #8 Encrypt edPrivateK eyInfo: "  + ioe);
  341                uke.init Cause(ioe) ;
  342                throw uk e;
  343           }
  344  
  345          try  {
  346                PBEParam eterSpec p beSpec;
  347                int ic =  0;
  348  
  349                if (algP arams != n ull) {
  350                    try  {
  351                         pbeSpec =
  352                             algPar ams.getPar ameterSpec (PBEParame terSpec.cl ass);
  353                    } ca tch (Inval idParamete rSpecExcep tion ipse)  {
  354                         throw new  IOExceptio n("Invalid  PBE algor ithm param eters");
  355                    }
  356                    ic =  pbeSpec.g etIteratio nCount();
  357  
  358                    if ( ic > MAX_I TERATION_C OUNT) {
  359                         throw new  IOExceptio n("PBE ite ration cou nt too lar ge");
  360                    }
  361                }
  362  
  363                byte[] k eyInfo;
  364                while (t rue) {
  365                    try  {
  366                         // Use JCE
  367                         SecretKey  skey = get PBEKey(pas sword);
  368                         Cipher cip her = Ciph er.getInst ance(
  369                             mapPBE ParamsToAl gorithm(al gOid, algP arams));
  370                         cipher.ini t(Cipher.D ECRYPT_MOD E, skey, a lgParams);
  371                         keyInfo =  cipher.doF inal(encry ptedKey);
  372                         break;
  373                    } ca tch (Excep tion e) {
  374                         if (passwo rd.length  == 0) {
  375                             // Ret ry using a n empty pa ssword
  376                             // wit hout a NUL L terminat or.
  377                             passwo rd = new c har[1];
  378                             contin ue;
  379                         }
  380                         throw e;
  381                    }
  382                }
  383  
  384                /*
  385                 * Parse  the key a lgorithm a nd then us e a JCA ke y factory
  386                 * to re -create th e key.
  387                 */
  388                DerValue  val = new  DerValue( keyInfo);
  389                DerInput Stream in  = val.toDe rInputStre am();
  390                int i =  in.getInte ger();
  391                DerValue [] value =  in.getSeq uence(2);
  392                Algorith mId algId  = new Algo rithmId(va lue[0].get OID());
  393                String k eyAlgo = a lgId.getNa me();
  394  
  395                // decod e private  key
  396                if (entr y instance of Private KeyEntry)  {
  397                    KeyF actory kfa c = KeyFac tory.getIn stance(key Algo);
  398                    PKCS 8EncodedKe ySpec kspe c = new PK CS8Encoded KeySpec(ke yInfo);
  399                    key  = kfac.gen eratePriva te(kspec);
  400  
  401                    if ( debug != n ull) {
  402                         debug.prin tln("Retri eved a pro tected pri vate key a t alias" +
  403                             " '" +  alias + " ' (" +
  404                             new Al gorithmId( algOid).ge tName() +
  405                             " iter ations: "  + ic + ")" );
  406                    }
  407  
  408                  // decode  PW        key
  409                } else {
  410                    byte [] keyByte s = in.get OctetStrin g();
  411                      SecretKeyS pec  PW      KeySpec =
  412                         new Secret KeySpec(ke yBytes, ke yAlgo);
  413  
  414                    // S pecial han dling requ ired for P BE: needs  a PBEKeySp ec
  415                    if ( keyAlgo.st artsWith(" PBE")) {
  416                         SecretKeyF actory sKe yFactory =
  417                             Secret KeyFactory .getInstan ce(keyAlgo );
  418                         KeySpec pb eKeySpec =
  419                               sKeyFactor y.getKeySp ec( PW      KeySpec, P BEKeySpec. class);
  420                         key = sKey Factory.ge nerateSecr et(pbeKeyS pec);
  421                    } el se {
  422                          key =  PW      KeySpec;
  423                    }
  424  
  425                    if ( debug != n ull) {
  426                          debug.prin tln("Retri eved a pro tected  PW        key at ali as " +
  427                             "'" +  alias + "'  (" +
  428                             new Al gorithmId( algOid).ge tName() +
  429                             " iter ations: "  + ic + ")" );
  430                    }
  431                }
  432           }  catch (Exc eption e)  {
  433                Unrecove rableKeyEx ception uk e =
  434                    new  Unrecovera bleKeyExce ption("Get  Key faile d: " +
  435                                               e.getMessa ge());
  436                uke.init Cause(e);
  437                throw uk e;
  438           }
  439           re turn key;
  440       }
  441  
  442       /**
  443        * Ret urns the c ertificate  chain ass ociated wi th the giv en alias.
  444        *
  445        * @pa ram alias  the alias  name
  446        *
  447        * @re turn the c ertificate  chain (or dered with  the user' s certific ate first
  448        * and  the root  certificat e authorit y last), o r null if  the given  alias
  449        * doe s not exis t or does  not contai n a certif icate chai n (i.e., t he given
  450        * ali as identif ies either  a <i>trus ted certif icate entr y</i> or a
  451        * <i> key entry< /i> withou t a certif icate chai n).
  452        */
  453       public  Certifica te[] engin eGetCertif icateChain (String al ias) {
  454           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  455           if  (entry !=  null && e ntry insta nceof Priv ateKeyEntr y) {
  456                if (((Pr ivateKeyEn try) entry ).chain ==  null) {
  457                    retu rn null;
  458                } else {
  459  
  460                    if ( debug != n ull) {
  461                         debug.prin tln("Retri eved a " +
  462                             ((Priv ateKeyEntr y) entry). chain.leng th +
  463                             "-cert ificate ch ain at ali as '" + al ias + "'") ;
  464                    }
  465  
  466                    retu rn ((Priva teKeyEntry ) entry).c hain.clone ();
  467                }
  468           }  else {
  469                return n ull;
  470           }
  471       }
  472  
  473       /**
  474        * Ret urns the c ertificate  associate d with the  given ali as.
  475        *
  476        * <p> If the giv en alias n ame identi fies a
  477        * <i> trusted ce rtificate  entry</i>,  the certi ficate ass ociated wi th that
  478        * ent ry is retu rned. If t he given a lias name  identifies  a
  479        * <i> key entry< /i>, the f irst eleme nt of the  certificat e chain of  that
  480        * ent ry is retu rned, or n ull if tha t entry do es not hav e a certif icate
  481        * cha in.
  482        *
  483        * @pa ram alias  the alias  name
  484        *
  485        * @re turn the c ertificate , or null  if the giv en alias d oes not ex ist or
  486        * doe s not cont ain a cert ificate.
  487        */
  488       public  Certifica te engineG etCertific ate(String  alias) {
  489           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  490           if  (entry ==  null) {
  491                return n ull;
  492           }
  493           if  (entry in stanceof C ertEntry & &
  494                ((CertEn try) entry ).trustedK eyUsage !=  null) {
  495  
  496                if (debu g != null)  {
  497                    if ( Arrays.equ als(AnyUsa ge,
  498                         ((CertEntr y) entry). trustedKey Usage)) {
  499                         debug.prin tln("Retri eved a cer tificate a t alias '"  + alias +
  500                             "' (tr usted for  any purpos e)");
  501                    } el se {
  502                         debug.prin tln("Retri eved a cer tificate a t alias '"  + alias +
  503                             "' (tr usted for  limited pu rposes)");
  504                    }
  505                }
  506  
  507                return ( (CertEntry ) entry).c ert;
  508  
  509           }  else if (e ntry insta nceof Priv ateKeyEntr y) {
  510                if (((Pr ivateKeyEn try) entry ).chain ==  null) {
  511                    retu rn null;
  512                } else {
  513  
  514                    if ( debug != n ull) {
  515                         debug.prin tln("Retri eved a cer tificate a t alias '"  + alias +
  516                             "'");
  517                    }
  518  
  519                    retu rn ((Priva teKeyEntry ) entry).c hain[0];
  520                }
  521  
  522           }  else {
  523                return n ull;
  524           }
  525       }
  526  
  527       /**
  528        * Ret urns the c reation da te of the  entry iden tified by  the given  alias.
  529        *
  530        * @pa ram alias  the alias  name
  531        *
  532        * @re turn the c reation da te of this  entry, or  null if t he given a lias does
  533        * not  exist
  534        */
  535       public  Date engi neGetCreat ionDate(St ring alias ) {
  536           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  537           if  (entry !=  null) {
  538                return n ew Date(en try.date.g etTime());
  539           }  else {
  540                return n ull;
  541           }
  542       }
  543  
  544       /**
  545        * Ass igns the g iven key t o the give n alias, p rotecting  it with th e given
  546        * pas sword.
  547        *
  548        * <p> If the giv en key is  of type <c ode>java.s ecurity.Pr ivateKey</ code>,
  549        * it  must be ac companied  by a certi ficate cha in certify ing the
  550        * cor responding  public ke y.
  551        *
  552        * <p> If the giv en alias a lready exi sts, the k eystore in formation
  553        * ass ociated wi th it is o verridden  by the giv en key (an d possibly
  554        * cer tificate c hain).
  555        *
  556        * @pa ram alias  the alias  name
  557        * @pa ram key th e key to b e associat ed with th e alias
  558        * @pa ram passwo rd the pas sword to p rotect the  key
  559        * @pa ram chain  the certif icate chai n for the  correspond ing public
  560        * key  (only req uired if t he given k ey is of t ype
  561        * <co de>java.se curity.Pri vateKey</c ode>).
  562        *
  563        * @ex ception Ke yStoreExce ption if t he given k ey cannot  be protect ed, or
  564        * thi s operatio n fails fo r some oth er reason
  565        */
  566       public  synchroni zed void e ngineSetKe yEntry(Str ing alias,  Key key,
  567                             char[]  password,  Certifica te[] chain )
  568           th rows KeySt oreExcepti on
  569       {
  570           Ke yStore.Pas swordProte ction pass wordProtec tion =
  571                new KeyS tore.Passw ordProtect ion(passwo rd);
  572  
  573           tr y {
  574                setKeyEn try(alias,  key, pass wordProtec tion, chai n, null);
  575  
  576           }  finally {
  577                try {
  578                    pass wordProtec tion.destr oy();
  579                } catch  (DestroyFa iledExcept ion dfe) {
  580                    // i gnore
  581                }
  582           }
  583       }
  584  
  585       /*
  586        * Set s a key en try (with  attributes , when pre sent)
  587        */
  588       privat e void set KeyEntry(S tring alia s, Key key ,
  589           Ke yStore.Pas swordProte ction pass wordProtec tion, Cert ificate[]  chain,
  590           Se t<KeyStore .Entry.Att ribute> at tributes)
  591                throws K eyStoreExc eption
  592       {
  593           tr y {
  594                Entry en try;
  595  
  596                if (key  instanceof  PrivateKe y) {
  597                    Priv ateKeyEntr y keyEntry  = new Pri vateKeyEnt ry();
  598                    keyE ntry.date  = new Date ();
  599  
  600                    if ( (key.getFo rmat().equ als("PKCS# 8")) ||
  601                         (key.getFo rmat().equ als("PKCS8 "))) {
  602  
  603                         if (debug  != null) {
  604                             debug. println(
  605                                 "S etting a p rotected p rivate key  at alias  '" +
  606                                 al ias + "'") ;
  607                             }
  608  
  609                         // Encrypt  the priva te key
  610                         keyEntry.p rotectedPr ivKey =
  611                             encryp tPrivateKe y(key.getE ncoded(),  passwordPr otection);
  612                    } el se {
  613                         throw new  KeyStoreEx ception("P rivate key  is not en coded" +
  614                                      "as PKCS #8");
  615                    }
  616  
  617                    // c lone the c hain
  618                    if ( chain != n ull) {
  619                         // validat e cert-cha in
  620                         if ((chain .length >  1) && (!va lidateChai n(chain)))
  621                            throw n ew KeyStor eException ("Certific ate chain  is " +
  622                                                       "n ot valid") ;
  623                         keyEntry.c hain = cha in.clone() ;
  624                         certificat eCount +=  chain.leng th;
  625  
  626                         if (debug  != null) {
  627                             debug. println("S etting a "  + chain.l ength +
  628                                 "- certificat e chain at  alias '"  + alias +  "'");
  629                         }
  630                    }
  631                    priv ateKeyCoun t++;
  632                    entr y = keyEnt ry;
  633  
  634                } else i f (key ins tanceof Se cretKey) {
  635                    Secr etKeyEntry  keyEntry  = new Secr etKeyEntry ();
  636                    keyE ntry.date  = new Date ();
  637  
  638                      // Encode  PW        key in a P KCS#8
  639                    DerO utputStrea m pkcs8 =  new DerOut putStream( );
  640                      DerOutputS tream  PW      KeyInfo =  new DerOut putStream( );
  641                      PW      KeyInfo.pu tInteger(0 );
  642                    Algo rithmId al gId = Algo rithmId.ge t(key.getA lgorithm() );
  643                      algId.enco de( PW      KeyInfo);
  644                      PW      KeyInfo.pu tOctetStri ng(key.get Encoded()) ;
  645                      pkcs8.writ e(DerValue .tag_Seque nce,  PW      KeyInfo);
  646  
  647                      // Encrypt  the  PW        key (using  same PBE  as for pri vate keys)
  648                    keyE ntry.prote ctedSecret Key =
  649                         encryptPri vateKey(pk cs8.toByte Array(), p asswordPro tection);
  650  
  651                    if ( debug != n ull) {
  652                          debug.prin tln("Setti ng a prote cted  PW        key at ali as '" +
  653                             alias  + "'");
  654                    }
  655                      PW      KeyCount++ ;
  656                    entr y = keyEnt ry;
  657  
  658                } else {
  659                    thro w new KeyS toreExcept ion("Unsup ported Key  type");
  660                }
  661  
  662                entry.at tributes =  new HashS et<>();
  663                if (attr ibutes !=  null) {
  664                    entr y.attribut es.addAll( attributes );
  665                }
  666                // set t he keyId t o current  date
  667                entry.ke yId = ("Ti me " + (en try.date). getTime()) .getBytes( "UTF8");
  668                // set t he alias
  669                entry.al ias = alia s.toLowerC ase(Locale .ENGLISH);
  670                // add t he entry
  671                entries. put(alias. toLowerCas e(Locale.E NGLISH), e ntry);
  672  
  673           }  catch (Exc eption nsa e) {
  674                throw ne w KeyStore Exception( "Key prote ction " +
  675                            " algor ithm not f ound: " +  nsae, nsae );
  676           }
  677       }
  678  
  679       /**
  680        * Ass igns the g iven key ( that has a lready bee n protecte d) to the  given
  681        * ali as.
  682        *
  683        * <p> If the pro tected key  is of typ e
  684        * <co de>java.se curity.Pri vateKey</c ode>, it m ust be acc ompanied b y a
  685        * cer tificate c hain certi fying the  correspond ing public  key. If t he
  686        * und erlying ke ystore imp lementatio n is of ty pe <code>j ks</code>,
  687        * <co de>key</co de> must b e encoded  as an
  688        * <co de>Encrypt edPrivateK eyInfo</co de> as def ined in th e PKCS #8  standard.
  689        *
  690        * <p> If the giv en alias a lready exi sts, the k eystore in formation
  691        * ass ociated wi th it is o verridden  by the giv en key (an d possibly
  692        * cer tificate c hain).
  693        *
  694        * @pa ram alias  the alias  name
  695        * @pa ram key th e key (in  protected  format) to  be associ ated with  the alias
  696        * @pa ram chain  the certif icate chai n for the  correspond ing public
  697        * key  (only use ful if the  protected  key is of  type
  698        * <co de>java.se curity.Pri vateKey</c ode>).
  699        *
  700        * @ex ception Ke yStoreExce ption if t his operat ion fails.
  701        */
  702       public  synchroni zed void e ngineSetKe yEntry(Str ing alias,  byte[] ke y,
  703                                        Certif icate[] ch ain)
  704           th rows KeySt oreExcepti on
  705       {
  706           //  Private k ey must be  encoded a s Encrypte dPrivateKe yInfo
  707           //  as define d in PKCS# 8
  708           tr y {
  709                new Encr yptedPriva teKeyInfo( key);
  710           }  catch (IOE xception i oe) {
  711                throw ne w KeyStore Exception( "Private k ey is not  stored"
  712                         + " as PKC S#8 Encryp tedPrivate KeyInfo: "  + ioe, io e);
  713           }
  714  
  715           Pr ivateKeyEn try entry  = new Priv ateKeyEntr y();
  716           en try.date =  new Date( );
  717  
  718           if  (debug !=  null) {
  719                debug.pr intln("Set ting a pro tected pri vate key a t alias '"  +
  720                    alia s + "'");
  721           }
  722  
  723           tr y {
  724                // set t he keyId t o current  date
  725                entry.ke yId = ("Ti me " + (en try.date). getTime()) .getBytes( "UTF8");
  726           }  catch (Uns upportedEn codingExce ption ex)  {
  727                // Won't  happen
  728           }
  729           //  set the a lias
  730           en try.alias  = alias.to LowerCase( Locale.ENG LISH);
  731  
  732           en try.protec tedPrivKey  = key.clo ne();
  733           if  (chain !=  null) {
  734                // valid ate cert-c hain
  735                if ((cha in.length  > 1) && (! validateCh ain(chain) )) {
  736                    thro w new KeyS toreExcept ion("Certi ficate cha in is "
  737                             + "not  valid");
  738                }
  739                entry.ch ain = chai n.clone();
  740                certific ateCount + = chain.le ngth;
  741  
  742                if (debu g != null)  {
  743                    debu g.println( "Setting a  " + entry .chain.len gth +
  744                         "-certific ate chain  at alias ' " + alias  + "'");
  745                }
  746           }
  747  
  748           //  add the e ntry
  749           pr ivateKeyCo unt++;
  750           en tries.put( alias.toLo werCase(Lo cale.ENGLI SH), entry );
  751       }
  752  
  753  
  754       /*
  755        * Gen erate rand om salt
  756        */
  757       privat e byte[] g etSalt()
  758       {
  759           //  Generate  a random s alt.
  760           by te[] salt  = new byte [SALT_LEN] ;
  761           if  (random = = null) {
  762               random =  new Secure Random();
  763           }
  764           ra ndom.nextB ytes(salt) ;
  765           re turn salt;
  766       }
  767  
  768       /*
  769        * Gen erate PBE  Algorithm  Parameters
  770        */
  771       privat e Algorith mParameter s getPBEAl gorithmPar ameters(St ring algor ithm)
  772           th rows IOExc eption
  773       {
  774           Al gorithmPar ameters al gParams =  null;
  775  
  776           //  create PB E paramete rs from sa lt and ite ration cou nt
  777           PB EParameter Spec param Spec =
  778                    new  PBEParamet erSpec(get Salt(), PB E_ITERATIO N_COUNT);
  779           tr y {
  780               algParams  = Algorit hmParamete rs.getInst ance(algor ithm);
  781               algParams .init(para mSpec);
  782           }  catch (Exc eption e)  {
  783               throw new  IOExcepti on("getPBE AlgorithmP arameters  failed: "  +
  784                                       e.getMe ssage(), e );
  785           }
  786           re turn algPa rams;
  787       }
  788  
  789       /*
  790        * par se Algorit hm Paramet ers
  791        */
  792       privat e Algorith mParameter s parseAlg Parameters (ObjectIde ntifier al gorithm,
  793           De rInputStre am in) thr ows IOExce ption
  794       {
  795           Al gorithmPar ameters al gParams =  null;
  796           tr y {
  797                DerValue  params;
  798                if (in.a vailable()  == 0) {
  799                    para ms = null;
  800                } else {
  801                    para ms = in.ge tDerValue( );
  802                    if ( params.tag  == DerVal ue.tag_Nul l) {
  803                       p arams = nu ll;
  804                    }
  805                }
  806                if (para ms != null ) {
  807                    if ( algorithm. equals((Ob ject)pbes2 _OID)) {
  808                         algParams  = Algorith mParameter s.getInsta nce("PBES2 ");
  809                    } el se {
  810                         algParams  = Algorith mParameter s.getInsta nce("PBE") ;
  811                    }
  812                    algP arams.init (params.to ByteArray( ));
  813                }
  814           }  catch (Exc eption e)  {
  815               throw new  IOExcepti on("parseA lgParamete rs failed:  " +
  816                                       e.getMe ssage(), e );
  817           }
  818           re turn algPa rams;
  819       }
  820  
  821       /*
  822        * Gen erate PBE  key
  823        */
  824       privat e SecretKe y getPBEKe y(char[] p assword) t hrows IOEx ception
  825       {
  826           Se cretKey sk ey = null;
  827  
  828           tr y {
  829                PBEKeySp ec keySpec  = new PBE KeySpec(pa ssword);
  830                SecretKe yFactory s kFac = Sec retKeyFact ory.getIns tance("PBE ");
  831                skey = s kFac.gener ateSecret( keySpec);
  832                keySpec. clearPassw ord();
  833           }  catch (Exc eption e)  {
  834               throw new  IOExcepti on("getSec retKey fai led: " +
  835                                       e.getMe ssage(), e );
  836           }
  837           re turn skey;
  838       }
  839  
  840       /*
  841        * Enc rypt priva te key usi ng Passwor d-based en cryption ( PBE)
  842        * as  defined in  PKCS#5.
  843        *
  844        * NOT E: By defa ult, pbeWi thSHAAnd3- KeyTripleD ES-CBC alg orithmID i s
  845        *        used to  derive th e key and  IV.
  846        *
  847        * @re turn encry pted priva te key enc oded as En cryptedPri vateKeyInf o
  848        */
  849       privat e byte[] e ncryptPriv ateKey(byt e[] data,
  850           Ke yStore.Pas swordProte ction pass wordProtec tion)
  851           th rows IOExc eption, No SuchAlgori thmExcepti on, Unreco verableKey Exception
  852       {
  853           by te[] key =  null;
  854  
  855           tr y {
  856                String a lgorithm;
  857                Algorith mParameter s algParam s;
  858                Algorith mId algid;
  859  
  860                // Initi alize PBE  algorithm  and parame ters
  861                algorith m = passwo rdProtecti on.getProt ectionAlgo rithm();
  862                if (algo rithm != n ull) {
  863                    Algo rithmParam eterSpec a lgParamSpe c =
  864                         passwordPr otection.g etProtecti onParamete rs();
  865                    if ( algParamSp ec != null ) {
  866                         algParams  = Algorith mParameter s.getInsta nce(algori thm);
  867                         algParams. init(algPa ramSpec);
  868                    } el se {
  869                         algParams  = getPBEAl gorithmPar ameters(al gorithm);
  870                    }
  871                } else {
  872                    // C heck defau lt key pro tection al gorithm fo r PKCS12 k eystores
  873                    algo rithm = Ac cessContro ller.doPri vileged(
  874                         new Privil egedAction <String>()  {
  875                             public  String ru n() {
  876                                 St ring prop  =
  877                                      Security .getProper ty(
  878                                          KEY_ PROTECTION _ALGORITHM [0]);
  879                                 if  (prop ==  null) {
  880                                      prop = S ecurity.ge tProperty(
  881                                          KEY_ PROTECTION _ALGORITHM [1]);
  882                                 }
  883                                 re turn prop;
  884                             }
  885                         });
  886                    if ( algorithm  == null ||  algorithm .isEmpty() ) {
  887                         algorithm  = "PBEWith SHA1AndDES ede";
  888                    }
  889                    algP arams = ge tPBEAlgori thmParamet ers(algori thm);
  890                }
  891  
  892                ObjectId entifier p beOID = ma pPBEAlgori thmToOID(a lgorithm);
  893                if (pbeO ID == null ) {
  894                         throw new  IOExceptio n("PBE alg orithm '"  + algorith m +
  895                             " 'is  not suppor ted for ke y entry pr otection") ;
  896                }
  897  
  898                // Use J CE
  899                SecretKe y skey = g etPBEKey(p asswordPro tection.ge tPassword( ));
  900                Cipher c ipher = Ci pher.getIn stance(alg orithm);
  901                cipher.i nit(Cipher .ENCRYPT_M ODE, skey,  algParams );
  902                byte[] e ncryptedKe y = cipher .doFinal(d ata);
  903                algid =  new Algori thmId(pbeO ID, cipher .getParame ters());
  904  
  905                if (debu g != null)  {
  906                    debu g.println( "  (Cipher  algorithm : " + ciph er.getAlgo rithm() +
  907                         ")");
  908                }
  909  
  910                // wrap  encrypted  private ke y in Encry ptedPrivat eKeyInfo
  911                // as de fined in P KCS#8
  912                Encrypte dPrivateKe yInfo encr Info =
  913                    new  EncryptedP rivateKeyI nfo(algid,  encrypted Key);
  914                key = en crInfo.get Encoded();
  915           }  catch (Exc eption e)  {
  916                Unrecove rableKeyEx ception uk e =
  917                    new  Unrecovera bleKeyExce ption("Enc rypt Priva te Key fai led: "
  918                                                       +  e.getMessa ge());
  919                uke.init Cause(e);
  920                throw uk e;
  921           }
  922  
  923           re turn key;
  924       }
  925  
  926       /*
  927        * Map  a PBE alg orithm nam e onto its  object id entifier
  928        */
  929       privat e static O bjectIdent ifier mapP BEAlgorith mToOID(Str ing algori thm)
  930           th rows NoSuc hAlgorithm Exception  {
  931           //  Check for  PBES2 alg orithms
  932           if  (algorith m.toLowerC ase(Locale .ENGLISH). startsWith ("pbewithh macsha"))  {
  933                return p bes2_OID;
  934           }
  935           re turn Algor ithmId.get (algorithm ).getOID() ;
  936       }
  937  
  938       /*
  939        * Map  a PBE alg orithm par ameters on to its alg orithm nam e
  940        */
  941       privat e static S tring mapP BEParamsTo Algorithm( ObjectIden tifier alg orithm,
  942           Al gorithmPar ameters al gParams) t hrows NoSu chAlgorith mException  {
  943           //  Check for  PBES2 alg orithms
  944           if  (algorith m.equals(( Object)pbe s2_OID) &&  algParams  != null)  {
  945                return a lgParams.t oString();
  946           }
  947           re turn algor ithm.toStr ing();
  948       }
  949  
  950       /**
  951        * Ass igns the g iven certi ficate to  the given  alias.
  952        *
  953        * <p> If the giv en alias a lready exi sts in thi s keystore  and ident ifies a
  954        * <i> trusted ce rtificate  entry</i>,  the certi ficate ass ociated wi th it is
  955        * ove rridden by  the given  certifica te.
  956        *
  957        * @pa ram alias  the alias  name
  958        * @pa ram cert t he certifi cate
  959        *
  960        * @ex ception Ke yStoreExce ption if t he given a lias alrea dy exists  and does
  961        * not  identify  a <i>trust ed certifi cate entry </i>, or t his operat ion fails
  962        * for  some othe r reason.
  963        */
  964       public  synchroni zed void e ngineSetCe rtificateE ntry(Strin g alias,
  965           Ce rtificate  cert) thro ws KeyStor eException
  966       {
  967           se tCertEntry (alias, ce rt, null);
  968       }
  969  
  970       /*
  971        * Set s a truste d cert ent ry (with a ttributes,  when pres ent)
  972        */
  973       privat e void set CertEntry( String ali as, Certif icate cert ,
  974           Se t<KeyStore .Entry.Att ribute> at tributes)  throws Key StoreExcep tion {
  975  
  976           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  977           if  (entry !=  null && e ntry insta nceof KeyE ntry) {
  978                throw ne w KeyStore Exception( "Cannot ov erwrite ow n certific ate");
  979           }
  980  
  981           Ce rtEntry ce rtEntry =
  982                new Cert Entry((X50 9Certifica te) cert,  null, alia s, AnyUsag e,
  983                    attr ibutes);
  984           ce rtificateC ount++;
  985           en tries.put( alias, cer tEntry);
  986  
  987           if  (debug !=  null) {
  988                debug.pr intln("Set ting a tru sted certi ficate at  alias '" +  alias +
  989                    "'") ;
  990           }
  991       }
  992  
  993       /**
  994        * Del etes the e ntry ident ified by t he given a lias from  this keyst ore.
  995        *
  996        * @pa ram alias  the alias  name
  997        *
  998        * @ex ception Ke yStoreExce ption if t he entry c annot be r emoved.
  999        */
  1000       public  synchroni zed void e ngineDelet eEntry(Str ing alias)
  1001           th rows KeySt oreExcepti on
  1002       {
  1003           if  (debug !=  null) {
  1004                debug.pr intln("Rem oving entr y at alias  '" + alia s + "'");
  1005           }
  1006  
  1007           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  1008           if  (entry in stanceof P rivateKeyE ntry) {
  1009                PrivateK eyEntry ke yEntry = ( PrivateKey Entry) ent ry;
  1010                if (keyE ntry.chain  != null)  {
  1011                    cert ificateCou nt -= keyE ntry.chain .length;
  1012                }
  1013                privateK eyCount--;
  1014           }  else if (e ntry insta nceof Cert Entry) {
  1015                certific ateCount-- ;
  1016           }  else if (e ntry insta nceof Secr etKeyEntry ) {
  1017                  PW      KeyCount-- ;
  1018           }
  1019           en tries.remo ve(alias.t oLowerCase (Locale.EN GLISH));
  1020       }
  1021  
  1022       /**
  1023        * Lis ts all the  alias nam es of this  keystore.
  1024        *
  1025        * @re turn enume ration of  the alias  names
  1026        */
  1027       public  Enumerati on<String>  engineAli ases() {
  1028           re turn Colle ctions.enu meration(e ntries.key Set());
  1029       }
  1030  
  1031       /**
  1032        * Che cks if the  given ali as exists  in this ke ystore.
  1033        *
  1034        * @pa ram alias  the alias  name
  1035        *
  1036        * @re turn true  if the ali as exists,  false oth erwise
  1037        */
  1038       public  boolean e ngineConta insAlias(S tring alia s) {
  1039           re turn entri es.contain sKey(alias .toLowerCa se(Locale. ENGLISH));
  1040       }
  1041  
  1042       /**
  1043        * Ret rieves the  number of  entries i n this key store.
  1044        *
  1045        * @re turn the n umber of e ntries in  this keyst ore
  1046        */
  1047       public  int engin eSize() {
  1048           re turn entri es.size();
  1049       }
  1050  
  1051       /**
  1052        * Ret urns true  if the ent ry identif ied by the  given ali as is a
  1053        * <i> key entry< /i>, and f alse other wise.
  1054        *
  1055        * @re turn true  if the ent ry identif ied by the  given ali as is a
  1056        * <i> key entry< /i>, false  otherwise .
  1057        */
  1058       public  boolean e ngineIsKey Entry(Stri ng alias)  {
  1059           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  1060           if  (entry !=  null && e ntry insta nceof KeyE ntry) {
  1061                return t rue;
  1062           }  else {
  1063                return f alse;
  1064           }
  1065       }
  1066  
  1067       /**
  1068        * Ret urns true  if the ent ry identif ied by the  given ali as is a
  1069        * <i> trusted ce rtificate  entry</i>,  and false  otherwise .
  1070        *
  1071        * @re turn true  if the ent ry identif ied by the  given ali as is a
  1072        * <i> trusted ce rtificate  entry</i>,  false oth erwise.
  1073        */
  1074       public  boolean e ngineIsCer tificateEn try(String  alias) {
  1075           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  1076           if  (entry !=  null && e ntry insta nceof Cert Entry &&
  1077                ((CertEn try) entry ).trustedK eyUsage !=  null) {
  1078                return t rue;
  1079           }  else {
  1080                return f alse;
  1081           }
  1082       }
  1083  
  1084       /**
  1085        * Det ermines if  the keyst ore {@code  Entry} fo r the spec ified
  1086        * {@c ode alias}  is an ins tance or s ubclass of  the speci fied
  1087        * {@c ode entryC lass}.
  1088        *
  1089        * @pa ram alias  the alias  name
  1090        * @pa ram entryC lass the e ntry class
  1091        *
  1092        * @re turn true  if the key store {@co de Entry}  for the sp ecified
  1093        *           {@co de alias}  is an inst ance or su bclass of  the
  1094        *           spec ified {@co de entryCl ass}, fals e otherwis e
  1095        *
  1096        * @si nce 1.5
  1097        */
  1098       @Overr ide
  1099       public  boolean
  1100           en gineEntryI nstanceOf( String ali as,
  1101                                    Class<? ex tends KeyS tore.Entry > entryCla ss)
  1102       {
  1103           if  (entryCla ss == KeyS tore.Trust edCertific ateEntry.c lass) {
  1104                return e ngineIsCer tificateEn try(alias) ;
  1105           }
  1106  
  1107           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  1108           if  (entryCla ss == KeyS tore.Priva teKeyEntry .class) {
  1109                return ( entry != n ull && ent ry instanc eof Privat eKeyEntry) ;
  1110           }
  1111           if  (entryCla ss == KeyS tore.Secre tKeyEntry. class) {
  1112                return ( entry != n ull && ent ry instanc eof Secret KeyEntry);
  1113           }
  1114           re turn false ;
  1115       }
  1116  
  1117       /**
  1118        * Ret urns the ( alias) nam e of the f irst keyst ore entry  whose cert ificate
  1119        * mat ches the g iven certi ficate.
  1120        *
  1121        * <p> This metho d attempts  to match  the given  certificat e with eac h
  1122        * key store entr y. If the  entry bein g consider ed
  1123        * is  a <i>trust ed certifi cate entry </i>, the  given cert ificate is
  1124        * com pared to t hat entry' s certific ate. If th e entry be ing consid ered is
  1125        * a < i>key entr y</i>, the  given cer tificate i s compared  to the fi rst
  1126        * ele ment of th at entry's  certifica te chain ( if a chain  exists).
  1127        *
  1128        * @pa ram cert t he certifi cate to ma tch with.
  1129        *
  1130        * @re turn the ( alias) nam e of the f irst entry  with matc hing certi ficate,
  1131        * or  null if no  such entr y exists i n this key store.
  1132        */
  1133       public  String en gineGetCer tificateAl ias(Certif icate cert ) {
  1134           Ce rtificate  certElem =  null;
  1135  
  1136           fo r (Enumera tion<Strin g> e = eng ineAliases (); e.hasM oreElement s(); ) {
  1137                String a lias = e.n extElement ();
  1138                Entry en try = entr ies.get(al ias);
  1139                if (entr y instance of Private KeyEntry)  {
  1140                    if ( ((PrivateK eyEntry) e ntry).chai n != null)  {
  1141                         certElem =  ((Private KeyEntry)  entry).cha in[0];
  1142                    }
  1143                } else i f (entry i nstanceof  CertEntry  &&
  1144                         ((CertEntr y) entry). trustedKey Usage != n ull) {
  1145                    cert Elem = ((C ertEntry)  entry).cer t;
  1146                } else {
  1147                    cont inue;
  1148                }
  1149                if (cert Elem != nu ll && cert Elem.equal s(cert)) {
  1150                    retu rn alias;
  1151                }
  1152           }
  1153           re turn null;
  1154       }
  1155  
  1156       /**
  1157        * Sto res this k eystore to  the given  output st ream, and  protects i ts
  1158        * int egrity wit h the give n password .
  1159        *
  1160        * @pa ram stream  the outpu t stream t o which th is keystor e is writt en.
  1161        * @pa ram passwo rd the pas sword to g enerate th e keystore  integrity  check
  1162        *
  1163        * @ex ception IO Exception  if there w as an I/O  problem wi th data
  1164        * @ex ception No SuchAlgori thmExcepti on if the  appropriat e data int egrity
  1165        * alg orithm cou ld not be  found
  1166        * @ex ception Ce rtificateE xception i f any of t he certifi cates incl uded in
  1167        * the  keystore  data could  not be st ored
  1168        */
  1169       public  synchroni zed void e ngineStore (OutputStr eam stream , char[] p assword)
  1170           th rows IOExc eption, No SuchAlgori thmExcepti on, Certif icateExcep tion
  1171       {
  1172           //  password  is mandato ry when st oring
  1173           if  (password  == null)  {
  1174               throw new  IllegalAr gumentExce ption("pas sword can' t be null" );
  1175           }
  1176  
  1177           //  -- Create  PFX
  1178           De rOutputStr eam pfx =  new DerOut putStream( );
  1179  
  1180           //  PFX versi on (always  write the  latest ve rsion)
  1181           De rOutputStr eam versio n = new De rOutputStr eam();
  1182           ve rsion.putI nteger(VER SION_3);
  1183           by te[] pfxVe rsion = ve rsion.toBy teArray();
  1184           pf x.write(pf xVersion);
  1185  
  1186           //  -- Create  AuthSafe
  1187           De rOutputStr eam authSa fe = new D erOutputSt ream();
  1188  
  1189           //  -- Create  ContentIn fos
  1190           De rOutputStr eam authSa feContentI nfo = new  DerOutputS tream();
  1191  
  1192           //  -- create  safeConte nt Data Co ntentInfo
  1193             if (privat eKeyCount  > 0 ||  PW      KeyCount >  0) {
  1194  
  1195                if (debu g != null)  {
  1196                      debug.prin tln("Stori ng " + (pr ivateKeyCo unt +  PW      KeyCount)  +
  1197                         " protecte d key(s) i n a PKCS#7  data");
  1198                }
  1199  
  1200                byte[] s afeContent Data = cre ateSafeCon tent();
  1201                ContentI nfo dataCo ntentInfo  = new Cont entInfo(sa feContentD ata);
  1202                dataCont entInfo.en code(authS afeContent Info);
  1203           }
  1204  
  1205           //  -- create  Encrypted ContentInf o
  1206           if  (certific ateCount >  0) {
  1207  
  1208                if (debu g != null)  {
  1209                    debu g.println( "Storing "  + certifi cateCount  +
  1210                         " certific ate(s) in  a PKCS#7 e ncryptedDa ta");
  1211                }
  1212  
  1213                byte[] e ncrData =  createEncr yptedData( password);
  1214                ContentI nfo encrCo ntentInfo  =
  1215                    new  ContentInf o(ContentI nfo.ENCRYP TED_DATA_O ID,
  1216                                      new DerV alue(encrD ata));
  1217                encrCont entInfo.en code(authS afeContent Info);
  1218           }
  1219  
  1220           //  wrap as S equenceOf  ContentInf os
  1221           De rOutputStr eam cInfo  = new DerO utputStrea m();
  1222           cI nfo.write( DerValue.t ag_Sequenc eOf, authS afeContent Info);
  1223           by te[] authe nticatedSa fe = cInfo .toByteArr ay();
  1224  
  1225           //  Create En capsulated  ContentIn fo
  1226           Co ntentInfo  contentInf o = new Co ntentInfo( authentica tedSafe);
  1227           co ntentInfo. encode(aut hSafe);
  1228           by te[] authS afeData =  authSafe.t oByteArray ();
  1229           pf x.write(au thSafeData );
  1230  
  1231           //  -- MAC
  1232           by te[] macDa ta = calcu lateMac(pa ssword, au thenticate dSafe);
  1233           pf x.write(ma cData);
  1234  
  1235           //  write PFX  to output  stream
  1236           De rOutputStr eam pfxout  = new Der OutputStre am();
  1237           pf xout.write (DerValue. tag_Sequen ce, pfx);
  1238           by te[] pfxDa ta = pfxou t.toByteAr ray();
  1239           st ream.write (pfxData);
  1240           st ream.flush ();
  1241       }
  1242  
  1243       /**
  1244        * Get s a <code> KeyStore.E ntry</code > for the  specified  alias
  1245        * wit h the spec ified prot ection par ameter.
  1246        *
  1247        * @pa ram alias  get the <c ode>KeySto re.Entry</ code> for  this alias
  1248        * @pa ram protPa ram the <c ode>Protec tionParame ter</code>
  1249        *           used  to protec t the <cod e>Entry</c ode>,
  1250        *           whic h may be < code>null< /code>
  1251        *
  1252        * @re turn the < code>KeySt ore.Entry< /code> for  the speci fied alias ,
  1253        *           or < code>null< /code> if  there is n o such ent ry
  1254        *
  1255        * @ex ception Ke yStoreExce ption if t he operati on failed
  1256        * @ex ception No SuchAlgori thmExcepti on if the  algorithm  for recove ring the
  1257        *           entr y cannot b e found
  1258        * @ex ception Un recoverabl eEntryExce ption if t he specifi ed
  1259        *           <cod e>protPara m</code> w ere insuff icient or  invalid
  1260        * @ex ception Un recoverabl eKeyExcept ion if the  entry is  a
  1261        *           <cod e>PrivateK eyEntry</c ode> or <c ode>Secret KeyEntry</ code>
  1262        *           and  the specif ied <code> protParam< /code> doe s not cont ain
  1263        *           the  informatio n needed t o recover  the key (e .g. wrong  password)
  1264        *
  1265        * @si nce 1.5
  1266        */
  1267       @Overr ide
  1268       public  KeyStore. Entry engi neGetEntry (String al ias,
  1269                             KeySto re.Protect ionParamet er protPar am)
  1270                    thro ws KeyStor eException , NoSuchAl gorithmExc eption,
  1271                    Unre coverableE ntryExcept ion {
  1272  
  1273           if  (!engineC ontainsAli as(alias))  {
  1274                return n ull;
  1275           }
  1276  
  1277           En try entry  = entries. get(alias. toLowerCas e(Locale.E NGLISH));
  1278           if  (protPara m == null)  {
  1279                if (engi neIsCertif icateEntry (alias)) {
  1280                    if ( entry inst anceof Cer tEntry &&
  1281                         ((CertEntr y) entry). trustedKey Usage != n ull) {
  1282  
  1283                         if (debug  != null) {
  1284                             debug. println("R etrieved a  trusted c ertificate  at " +
  1285                                 "a lias '" +  alias + "' ");
  1286                         }
  1287  
  1288                         return new  KeyStore. TrustedCer tificateEn try(
  1289                             ((Cert Entry)entr y).cert, g etAttribut es(entry)) ;
  1290                    }
  1291                } else {
  1292                    thro w new Unre coverableK eyExceptio n
  1293                             ("requ ested entr y requires  a passwor d");
  1294                }
  1295           }
  1296  
  1297           if  (protPara m instance of KeyStor e.Password Protection ) {
  1298                if (engi neIsCertif icateEntry (alias)) {
  1299                    thro w new Unsu pportedOpe rationExce ption
  1300                         ("trusted  certificat e entries  are not pa ssword-pro tected");
  1301                } else i f (engineI sKeyEntry( alias)) {
  1302                    KeyS tore.Passw ordProtect ion pp =
  1303                             (KeySt ore.Passwo rdProtecti on)protPar am;
  1304                    char [] passwor d = pp.get Password() ;
  1305  
  1306                    Key  key = engi neGetKey(a lias, pass word);
  1307                    if ( key instan ceof Priva teKey) {
  1308                         Certificat e[] chain  = engineGe tCertifica teChain(al ias);
  1309  
  1310                         return new  KeyStore. PrivateKey Entry((Pri vateKey)ke y, chain,
  1311                             getAtt ributes(en try));
  1312  
  1313                    } el se if (key  instanceo f SecretKe y) {
  1314  
  1315                         return new  KeyStore. SecretKeyE ntry((Secr etKey)key,
  1316                             getAtt ributes(en try));
  1317                    }
  1318                } else i f (!engine IsKeyEntry (alias)) {
  1319                    thro w new Unsu pportedOpe rationExce ption
  1320                         ("untruste d certific ate entrie s are not  " +
  1321                             "passw ord-protec ted");
  1322                }
  1323           }
  1324  
  1325           th row new Un supportedO perationEx ception();
  1326       }
  1327  
  1328       /**
  1329        * Sav es a <code >KeyStore. Entry</cod e> under t he specifi ed alias.
  1330        * The  specified  protectio n paramete r is used  to protect  the
  1331        * <co de>Entry</ code>.
  1332        *
  1333        * <p>  If an ent ry already  exists fo r the spec ified alia s,
  1334        * it  is overrid den.
  1335        *
  1336        * @pa ram alias  save the < code>KeySt ore.Entry< /code> und er this al ias
  1337        * @pa ram entry  the <code> Entry</cod e> to save
  1338        * @pa ram protPa ram the <c ode>Protec tionParame ter</code>
  1339        *           used  to protec t the <cod e>Entry</c ode>,
  1340        *           whic h may be < code>null< /code>
  1341        *
  1342        * @ex ception Ke yStoreExce ption if t his operat ion fails
  1343        *
  1344        * @si nce 1.5
  1345        */
  1346       @Overr ide
  1347       public  synchroni zed void e ngineSetEn try(String  alias, Ke yStore.Ent ry entry,
  1348           Ke yStore.Pro tectionPar ameter pro tParam) th rows KeySt oreExcepti on {
  1349  
  1350           //  get passw ord
  1351           if  (protPara m != null  &&
  1352                !(protPa ram instan ceof KeySt ore.Passwo rdProtecti on)) {
  1353                throw ne w KeyStore Exception( "unsupport ed protect ion parame ter");
  1354           }
  1355           Ke yStore.Pas swordProte ction pPro tect = nul l;
  1356           if  (protPara m != null)  {
  1357                pProtect  = (KeySto re.Passwor dProtectio n)protPara m;
  1358           }
  1359  
  1360           //  set entry
  1361           if  (entry in stanceof K eyStore.Tr ustedCerti ficateEntr y) {
  1362                if (prot Param != n ull && pPr otect.getP assword()  != null) {
  1363                    // p re-1.5 sty le setCert ificateEnt ry did not  allow pas sword
  1364                    thro w new KeyS toreExcept ion
  1365                         ("trusted  certificat e entries  are not pa ssword-pro tected");
  1366                } else {
  1367                    KeyS tore.Trust edCertific ateEntry t ce =
  1368                             (KeySt ore.Truste dCertifica teEntry)en try;
  1369                    setC ertEntry(a lias, tce. getTrusted Certificat e(),
  1370                         tce.getAtt ributes()) ;
  1371  
  1372                    retu rn;
  1373                }
  1374           }  else if (e ntry insta nceof KeyS tore.Priva teKeyEntry ) {
  1375                if (pPro tect == nu ll || pPro tect.getPa ssword() = = null) {
  1376                    // p re-1.5 sty le setKeyE ntry requi red passwo rd
  1377                    thro w new KeyS toreExcept ion
  1378                         ("non-null  password  required t o create P rivateKeyE ntry");
  1379                } else {
  1380                    KeyS tore.Priva teKeyEntry  pke = (Ke yStore.Pri vateKeyEnt ry)entry;
  1381                    setK eyEntry(al ias, pke.g etPrivateK ey(), pPro tect,
  1382                         pke.getCer tificateCh ain(), pke .getAttrib utes());
  1383  
  1384                    retu rn;
  1385                }
  1386           }  else if (e ntry insta nceof KeyS tore.Secre tKeyEntry)  {
  1387                if (pPro tect == nu ll || pPro tect.getPa ssword() = = null) {
  1388                    // p re-1.5 sty le setKeyE ntry requi red passwo rd
  1389                    thro w new KeyS toreExcept ion
  1390                         ("non-null  password  required t o create S ecretKeyEn try");
  1391                } else {
  1392                    KeyS tore.Secre tKeyEntry  ske = (Key Store.Secr etKeyEntry )entry;
  1393                    setK eyEntry(al ias, ske.g etSecretKe y(), pProt ect,
  1394                         (Certifica te[])null,  ske.getAt tributes() );
  1395  
  1396                    retu rn;
  1397                }
  1398           }
  1399  
  1400           th row new Ke yStoreExce ption
  1401                    ("un supported  entry type : " + entr y.getClass ().getName ());
  1402       }
  1403  
  1404       /*
  1405        * Ass emble the  entry attr ibutes
  1406        */
  1407       privat e Set<KeyS tore.Entry .Attribute > getAttri butes(Entr y entry) {
  1408  
  1409           if  (entry.at tributes = = null) {
  1410                entry.at tributes =  new HashS et<>();
  1411           }
  1412  
  1413           //  friendlyN ame
  1414           en try.attrib utes.add(n ew PKCS12A ttribute(
  1415                PKCS9Fri endlyName_ OID.toStri ng(), entr y.alias));
  1416  
  1417           //  localKeyI D
  1418           by te[] keyId Value = en try.keyId;
  1419           if  (keyIdVal ue != null ) {
  1420                entry.at tributes.a dd(new PKC S12Attribu te(
  1421                    PKCS 9LocalKeyI d_OID.toSt ring(), De bug.toStri ng(keyIdVa lue)));
  1422           }
  1423  
  1424           //  trustedKe yUsage
  1425           if  (entry in stanceof C ertEntry)  {
  1426                ObjectId entifier[]  trustedKe yUsageValu e =
  1427                    ((Ce rtEntry) e ntry).trus tedKeyUsag e;
  1428                if (trus tedKeyUsag eValue !=  null) {
  1429                    if ( trustedKey UsageValue .length ==  1) { // o mit bracke ts
  1430                         entry.attr ibutes.add (new PKCS1 2Attribute (
  1431                             Truste dKeyUsage_ OID.toStri ng(),
  1432                             truste dKeyUsageV alue[0].to String())) ;
  1433                    } el se { // mu lti-valued
  1434                         entry.attr ibutes.add (new PKCS1 2Attribute (
  1435                             Truste dKeyUsage_ OID.toStri ng(),
  1436                             Arrays .toString( trustedKey UsageValue )));
  1437                    }
  1438                }
  1439           }
  1440  
  1441           re turn entry .attribute s;
  1442       }
  1443  
  1444       /*
  1445        * Gen erate Hash .
  1446        */
  1447       privat e byte[] g enerateHas h(byte[] d ata) throw s IOExcept ion
  1448       {
  1449           by te[] diges t = null;
  1450  
  1451           tr y {
  1452                MessageD igest md =  MessageDi gest.getIn stance("SH A1");
  1453                md.updat e(data);
  1454                digest =  md.digest ();
  1455           }  catch (Exc eption e)  {
  1456                throw ne w IOExcept ion("gener ateHash fa iled: " +  e, e);
  1457           }
  1458           re turn diges t;
  1459       }
  1460  
  1461  
  1462       /*
  1463        * Cal culate MAC  using HMA C algorith m (require d for pass word integ rity)
  1464        *
  1465          * Hash-bas ed MAC alg orithm com bines  PW        key with m essage dig est to
  1466        * cre ate a mess age authen tication c ode (MAC)
  1467        */
  1468       privat e byte[] c alculateMa c(char[] p asswd, byt e[] data)
  1469           th rows IOExc eption
  1470       {
  1471           by te[] mData  = null;
  1472           St ring algNa me = "SHA1 ";
  1473  
  1474           tr y {
  1475                // Gener ate a rand om salt.
  1476                byte[] s alt = getS alt();
  1477  
  1478                // gener ate MAC (M AC key is  generated  within JCE )
  1479                Mac m =  Mac.getIns tance("Hma cPBESHA1") ;
  1480                PBEParam eterSpec p arams =
  1481                             new PB EParameter Spec(salt,  MAC_ITERA TION_COUNT );
  1482                SecretKe y key = ge tPBEKey(pa sswd);
  1483                m.init(k ey, params );
  1484                m.update (data);
  1485                byte[] m acResult =  m.doFinal ();
  1486  
  1487                // encod e as MacDa ta
  1488                MacData  macData =  new MacDat a(algName,  macResult , salt,
  1489                                                       MA C_ITERATIO N_COUNT);
  1490                DerOutpu tStream by tes = new  DerOutputS tream();
  1491                bytes.wr ite(macDat a.getEncod ed());
  1492                mData =  bytes.toBy teArray();
  1493           }  catch (Exc eption e)  {
  1494                throw ne w IOExcept ion("calcu lateMac fa iled: " +  e, e);
  1495           }
  1496           re turn mData ;
  1497       }
  1498  
  1499  
  1500       /*
  1501        * Val idate Cert ificate Ch ain
  1502        */
  1503       privat e boolean  validateCh ain(Certif icate[] ce rtChain)
  1504       {
  1505           fo r (int i =  0; i < ce rtChain.le ngth-1; i+ +) {
  1506                X500Prin cipal issu erDN =
  1507                    ((X5 09Certific ate)certCh ain[i]).ge tIssuerX50 0Principal ();
  1508                X500Prin cipal subj ectDN =
  1509                    ((X5 09Certific ate)certCh ain[i+1]). getSubject X500Princi pal();
  1510                if (!(is suerDN.equ als(subjec tDN)))
  1511                    retu rn false;
  1512           }
  1513  
  1514           //  Check for  loops in  the chain.  If there  are repeat ed certs,
  1515           //  the Set o f certs in  the chain  will cont ain fewer  certs than
  1516           //  the chain
  1517           Se t<Certific ate> set =  new HashS et<>(Array s.asList(c ertChain)) ;
  1518           re turn set.s ize() == c ertChain.l ength;
  1519       }
  1520  
  1521  
  1522       /*
  1523        * Cre ate PKCS#1 2 Attribut es, friend lyName, lo calKeyId a nd trusted KeyUsage.
  1524        *
  1525        * Alt hough attr ibutes are  optional,  they coul d be requi red.
  1526        * For  e.g. loca lKeyId att ribute is  required t o match th e
  1527        * pri vate key w ith the as sociated e nd-entity  certificat e.
  1528        * The  trustedKe yUsage att ribute is  used to de note a tru sted certi ficate.
  1529        *
  1530        * PKC S8Shrouded KeyBags in clude uniq ue localKe yID and fr iendlyName .
  1531        * Cer tBags may  or may not  include a ttributes  depending  on the typ e
  1532        * of  Certificat e. In end- entity cer tificates,  localKeyI D should b e
  1533        * uni que, and t he corresp onding pri vate key s hould have  the same
  1534        * loc alKeyID. F or trusted  CA certs  in the cer t-chain, l ocalKeyID
  1535        * att ribute is  not requir ed, hence  most vendo rs don't i nclude it.
  1536        * NSS /Netscape  require it  to be uni que or nul l, where a s IE/OpenS SL
  1537        * ign ore it.
  1538        *
  1539        * Her e is a lis t of pkcs1 2 attribut e values i n CertBags .
  1540        *
  1541        * PKC S12 Attrib ute        NSS/Netsca pe    IE      OpenSSL     J2SE
  1542        * --- ---------- ---------- ---------- ---------- ---------- ---------
  1543        * Loc alKeyId
  1544        * (In  EE cert o nly,
  1545        *  NU LL in CA c erts)       true           true      true       true
  1546        *
  1547        * fri endlyName              unique         same/     same/      unique
  1548        *                                           uniqu e   unique /
  1549        *                                                     null
  1550        * tru stedKeyUsa ge          -              -         -          true
  1551        *
  1552        * Not e: OpenSSL  adds frie ndlyName f or end-ent ity cert o nly, and
  1553        * rem oves the l ocalKeyID  and friend lyName for  CA certs.
  1554        * If  the CertBa g did not  have a fri endlyName,  most vend ors will
  1555        * add  it, and a ssign it t o the DN o f the cert .
  1556        */
  1557       privat e byte[] g etBagAttri butes(Stri ng alias,  byte[] key Id,
  1558           Se t<KeyStore .Entry.Att ribute> at tributes)  throws IOE xception {
  1559           re turn getBa gAttribute s(alias, k eyId, null , attribut es);
  1560       }
  1561  
  1562       privat e byte[] g etBagAttri butes(Stri ng alias,  byte[] key Id,
  1563           Ob jectIdenti fier[] tru stedUsage,
  1564           Se t<KeyStore .Entry.Att ribute> at tributes)  throws IOE xception {
  1565  
  1566           by te[] local KeyID = nu ll;
  1567           by te[] frien dlyName =  null;
  1568           by te[] trust edKeyUsage  = null;
  1569  
  1570           //  return nu ll if all  three attr ibutes are  null
  1571           if  ((alias = = null) &&  (keyId ==  null) &&  (trustedKe yUsage ==  null)) {
  1572                return n ull;
  1573           }
  1574  
  1575           //  SafeBag A ttributes
  1576           De rOutputStr eam bagAtt rs = new D erOutputSt ream();
  1577  
  1578           //  Encode th e friendly name oid.
  1579           if  (alias !=  null) {
  1580                DerOutpu tStream ba gAttr1 = n ew DerOutp utStream() ;
  1581                bagAttr1 .putOID(PK CS9Friendl yName_OID) ;
  1582                DerOutpu tStream ba gAttrConte nt1 = new  DerOutputS tream();
  1583                DerOutpu tStream ba gAttrValue 1 = new De rOutputStr eam();
  1584                bagAttrC ontent1.pu tBMPString (alias);
  1585                bagAttr1 .write(Der Value.tag_ Set, bagAt trContent1 );
  1586                bagAttrV alue1.writ e(DerValue .tag_Seque nce, bagAt tr1);
  1587                friendly Name = bag AttrValue1 .toByteArr ay();
  1588           }
  1589  
  1590           //  Encode th e localkey Id oid.
  1591           if  (keyId !=  null) {
  1592                DerOutpu tStream ba gAttr2 = n ew DerOutp utStream() ;
  1593                bagAttr2 .putOID(PK CS9LocalKe yId_OID);
  1594                DerOutpu tStream ba gAttrConte nt2 = new  DerOutputS tream();
  1595                DerOutpu tStream ba gAttrValue 2 = new De rOutputStr eam();
  1596                bagAttrC ontent2.pu tOctetStri ng(keyId);
  1597                bagAttr2 .write(Der Value.tag_ Set, bagAt trContent2 );
  1598                bagAttrV alue2.writ e(DerValue .tag_Seque nce, bagAt tr2);
  1599                localKey ID = bagAt trValue2.t oByteArray ();
  1600           }
  1601  
  1602           //  Encode th e trustedK eyUsage oi d.
  1603           if  (trustedU sage != nu ll) {
  1604                DerOutpu tStream ba gAttr3 = n ew DerOutp utStream() ;
  1605                bagAttr3 .putOID(Tr ustedKeyUs age_OID);
  1606                DerOutpu tStream ba gAttrConte nt3 = new  DerOutputS tream();
  1607                DerOutpu tStream ba gAttrValue 3 = new De rOutputStr eam();
  1608                for (Obj ectIdentif ier usage  : trustedU sage) {
  1609                    bagA ttrContent 3.putOID(u sage);
  1610                }
  1611                bagAttr3 .write(Der Value.tag_ Set, bagAt trContent3 );
  1612                bagAttrV alue3.writ e(DerValue .tag_Seque nce, bagAt tr3);
  1613                trustedK eyUsage =  bagAttrVal ue3.toByte Array();
  1614           }
  1615  
  1616           De rOutputStr eam attrs  = new DerO utputStrea m();
  1617           if  (friendly Name != nu ll) {
  1618                attrs.wr ite(friend lyName);
  1619           }
  1620           if  (localKey ID != null ) {
  1621                attrs.wr ite(localK eyID);
  1622           }
  1623           if  (trustedK eyUsage !=  null) {
  1624                attrs.wr ite(truste dKeyUsage) ;
  1625           }
  1626  
  1627           if  (attribut es != null ) {
  1628                for (Key Store.Entr y.Attribut e attribut e : attrib utes) {
  1629                    Stri ng attribu teName = a ttribute.g etName();
  1630                    // s kip friend lyName, lo calKeyId a nd trusted KeyUsage
  1631                    if ( CORE_ATTRI BUTES[0].e quals(attr ibuteName)  ||
  1632                         CORE_ATTRI BUTES[1].e quals(attr ibuteName)  ||
  1633                         CORE_ATTRI BUTES[2].e quals(attr ibuteName) ) {
  1634                         continue;
  1635                    }
  1636                    attr s.write((( PKCS12Attr ibute) att ribute).ge tEncoded() );
  1637                }
  1638           }
  1639  
  1640           ba gAttrs.wri te(DerValu e.tag_Set,  attrs);
  1641           re turn bagAt trs.toByte Array();
  1642       }
  1643  
  1644       /*
  1645        * Cre ate Encryp tedData co ntent type , that con tains Encr yptedConte ntInfo.
  1646        * Inc ludes cert ificates i n individu al SafeBag s of type  CertBag.
  1647        * Eac h CertBag  may includ e pkcs12 a ttributes
  1648        * (se e comments  in getBag Attributes )
  1649        */
  1650       privat e byte[] c reateEncry ptedData(c har[] pass word)
  1651           th rows Certi ficateExce ption, IOE xception
  1652       {
  1653           De rOutputStr eam out =  new DerOut putStream( );
  1654           fo r (Enumera tion<Strin g> e = eng ineAliases (); e.hasM oreElement s(); ) {
  1655  
  1656                String a lias = e.n extElement ();
  1657                Entry en try = entr ies.get(al ias);
  1658  
  1659                // certi ficate cha in
  1660                Certific ate[] cert s;
  1661  
  1662                if (entr y instance of Private KeyEntry)  {
  1663                    Priv ateKeyEntr y keyEntry  = (Privat eKeyEntry)  entry;
  1664                    if ( keyEntry.c hain != nu ll) {
  1665                         certs = ke yEntry.cha in;
  1666                    } el se {
  1667                         certs = ne w Certific ate[0];
  1668                    }
  1669                } else i f (entry i nstanceof  CertEntry)  {
  1670                    cert s = new Ce rtificate[ ]{((CertEn try) entry ).cert};
  1671                } else {
  1672                    cert s = new Ce rtificate[ 0];
  1673                }
  1674  
  1675                for (int  i = 0; i  < certs.le ngth; i++)  {
  1676                    // c reate Safe Bag of Typ e CertBag
  1677                    DerO utputStrea m safeBag  = new DerO utputStrea m();
  1678                    safe Bag.putOID (CertBag_O ID);
  1679  
  1680                    // c reate a Ce rtBag
  1681                    DerO utputStrea m certBag  = new DerO utputStrea m();
  1682                    cert Bag.putOID (PKCS9Cert Type_OID);
  1683  
  1684                    // w rite encod ed certs i n a contex t-specific  tag
  1685                    DerO utputStrea m certValu e = new De rOutputStr eam();
  1686                    X509 Certificat e cert = ( X509Certif icate) cer ts[i];
  1687                    cert Value.putO ctetString (cert.getE ncoded());
  1688                    cert Bag.write( DerValue.c reateTag(D erValue.TA G_CONTEXT,
  1689                                               true, (byt e) 0), cer tValue);
  1690  
  1691                    // w rap CertBa g in a Seq uence
  1692                    DerO utputStrea m certout  = new DerO utputStrea m();
  1693                    cert out.write( DerValue.t ag_Sequenc e, certBag );
  1694                    byte [] certBag Value = ce rtout.toBy teArray();
  1695  
  1696                    // W rap the Ce rtBag enco ding in a  context-sp ecific tag .
  1697                    DerO utputStrea m bagValue  = new Der OutputStre am();
  1698                    bagV alue.write (certBagVa lue);
  1699                    // w rite SafeB ag Value
  1700                    safe Bag.write( DerValue.c reateTag(D erValue.TA G_CONTEXT,
  1701                                      true, (b yte) 0), b agValue);
  1702  
  1703                    // w rite SafeB ag Attribu tes
  1704                    // A ll Certs s hould have  a unique  friendlyNa me.
  1705                    // T his change  is made t o meet NSS  requireme nts.
  1706                    byte [] bagAttr s = null;
  1707                    if ( i == 0) {
  1708                         // Only En d-Entity C ert should  have a lo calKeyId.
  1709                         if (entry  instanceof  KeyEntry)  {
  1710                             KeyEnt ry keyEntr y = (KeyEn try) entry ;
  1711                             bagAtt rs =
  1712                                 ge tBagAttrib utes(keyEn try.alias,  keyEntry. keyId,
  1713                                      keyEntry .attribute s);
  1714                         } else {
  1715                             CertEn try certEn try = (Cer tEntry) en try;
  1716                             bagAtt rs =
  1717                                 ge tBagAttrib utes(certE ntry.alias , certEntr y.keyId,
  1718                                      certEntr y.trustedK eyUsage,
  1719                                      certEntr y.attribut es);
  1720                         }
  1721                    } el se {
  1722                         // Trusted  root CA c erts and I ntermediat e CA certs  do not
  1723                         // need to  have a lo calKeyId,  and hence  localKeyId  is null
  1724                         // This ch ange is ma de to meet  NSS/Netsc ape requir ements.
  1725                         // NSS pkc s12 librar y requires  trusted C A certs in  the
  1726                         // certifi cate chain  to have u nique or n ull localK eyID.
  1727                         // However , IE/OpenS SL do not  impose thi s restrict ion.
  1728                         bagAttrs =  getBagAtt ributes(
  1729                                 ce rt.getSubj ectX500Pri ncipal().g etName(),  null,
  1730                                 en try.attrib utes);
  1731                    }
  1732                    if ( bagAttrs ! = null) {
  1733                         safeBag.wr ite(bagAtt rs);
  1734                    }
  1735  
  1736                    // w rap as Seq uence
  1737                    out. write(DerV alue.tag_S equence, s afeBag);
  1738                } // for  cert-chai n
  1739           }
  1740  
  1741           //  wrap as S equenceOf  SafeBag
  1742           De rOutputStr eam safeBa gValue = n ew DerOutp utStream() ;
  1743           sa feBagValue .write(Der Value.tag_ SequenceOf , out);
  1744           by te[] safeB agData = s afeBagValu e.toByteAr ray();
  1745  
  1746           //  encrypt t he content  (Encrypte dContentIn fo)
  1747           by te[] encrC ontentInfo  = encrypt Content(sa feBagData,  password) ;
  1748  
  1749           //  -- SEQUEN CE of Encr yptedData
  1750           De rOutputStr eam encrDa ta = new D erOutputSt ream();
  1751           De rOutputStr eam encrDa taContent  = new DerO utputStrea m();
  1752           en crData.put Integer(0) ;
  1753           en crData.wri te(encrCon tentInfo);
  1754           en crDataCont ent.write( DerValue.t ag_Sequenc e, encrDat a);
  1755           re turn encrD ataContent .toByteArr ay();
  1756       }
  1757  
  1758       /*
  1759        * Cre ate SafeCo ntent Data  content t ype.
  1760          * Includes  encrypted   PW        key in a S afeBag of  type Secre tBag.
  1761        * Inc ludes encr ypted priv ate key in  a SafeBag  of type P KCS8Shroud edKeyBag.
  1762        * Eac h PKCS8Shr oudedKeyBa g includes  pkcs12 at tributes
  1763        * (se e comments  in getBag Attributes )
  1764        */
  1765       privat e byte[] c reateSafeC ontent()
  1766           th rows Certi ficateExce ption, IOE xception {
  1767  
  1768           De rOutputStr eam out =  new DerOut putStream( );
  1769           fo r (Enumera tion<Strin g> e = eng ineAliases (); e.hasM oreElement s(); ) {
  1770  
  1771                String a lias = e.n extElement ();
  1772                Entry en try = entr ies.get(al ias);
  1773                if (entr y == null  || (!(entr y instance of KeyEntr y))) {
  1774                    cont inue;
  1775                }
  1776                DerOutpu tStream sa feBag = ne w DerOutpu tStream();
  1777                KeyEntry  keyEntry  = (KeyEntr y) entry;
  1778  
  1779                // DER e ncode the  private ke y
  1780                if (keyE ntry insta nceof Priv ateKeyEntr y) {
  1781                    // C reate Safe Bag of typ e pkcs8Shr oudedKeyBa g
  1782                    safe Bag.putOID (PKCS8Shro udedKeyBag _OID);
  1783  
  1784                    // g et the enc rypted pri vate key
  1785                    byte [] encrByt es = ((Pri vateKeyEnt ry)keyEntr y).protect edPrivKey;
  1786                    Encr yptedPriva teKeyInfo  encrInfo =  null;
  1787                    try  {
  1788                         encrInfo =  new Encry ptedPrivat eKeyInfo(e ncrBytes);
  1789  
  1790                    } ca tch (IOExc eption ioe ) {
  1791                         throw new  IOExceptio n("Private  key not s tored as "
  1792                                 +  "PKCS#8 En cryptedPri vateKeyInf o"
  1793                                 +  ioe.getMes sage());
  1794                    }
  1795  
  1796                    // W rap the En cryptedPri vateKeyInf o in a con text-speci fic tag.
  1797                    DerO utputStrea m bagValue  = new Der OutputStre am();
  1798                    bagV alue.write (encrInfo. getEncoded ());
  1799                    safe Bag.write( DerValue.c reateTag(D erValue.TA G_CONTEXT,
  1800                                      true, (b yte) 0), b agValue);
  1801  
  1802                  // DER enc ode the  PW        key
  1803                } else i f (keyEntr y instance of SecretK eyEntry) {
  1804                    // C reate Safe Bag of typ e SecretBa g
  1805                    safe Bag.putOID (SecretBag _OID);
  1806  
  1807                    // C reate a Se cretBag
  1808                      DerOutputS tream  PW      Bag = new  DerOutputS tream();
  1809                      PW      Bag.putOID (PKCS8Shro udedKeyBag _OID);
  1810  
  1811                      // Write  PW        key in a c ontext-spe cific tag
  1812                      DerOutputS tream  PW      KeyValue =  new DerOu tputStream ();
  1813                      PW      KeyValue.p utOctetStr ing(
  1814                         ((SecretKe yEntry) ke yEntry).pr otectedSec retKey);
  1815                      PW      Bag.write( DerValue.c reateTag(D erValue.TA G_CONTEXT,
  1816                                                true, (byt e) 0),  PW      KeyValue);
  1817  
  1818                    // W rap Secret Bag in a S equence
  1819                      DerOutputS tream  PW      BagSeq = n ew DerOutp utStream() ;
  1820                      PW      BagSeq.wri te(DerValu e.tag_Sequ ence,  PW      Bag);
  1821                      byte[]  PW      BagValue =   PW      BagSeq.toB yteArray() ;
  1822  
  1823                      // Wrap th PW        bag in a c ontext-spe cific tag.
  1824                    DerO utputStrea m bagValue  = new Der OutputStre am();
  1825                      bagValue.w rite( PW      BagValue);
  1826  
  1827                    // W rite SafeB ag value
  1828                    safe Bag.write( DerValue.c reateTag(D erValue.TA G_CONTEXT,
  1829                                          true , (byte) 0 ), bagValu e);
  1830                } else {
  1831                    cont inue; // s kip this e ntry
  1832                }
  1833  
  1834                // write  SafeBag A ttributes
  1835                byte[] b agAttrs =
  1836                    getB agAttribut es(alias,  entry.keyI d, entry.a ttributes) ;
  1837                safeBag. write(bagA ttrs);
  1838  
  1839                // wrap  as Sequenc e
  1840                out.writ e(DerValue .tag_Seque nce, safeB ag);
  1841           }
  1842  
  1843           //  wrap as S equence
  1844           De rOutputStr eam safeBa gValue = n ew DerOutp utStream() ;
  1845           sa feBagValue .write(Der Value.tag_ Sequence,  out);
  1846           re turn safeB agValue.to ByteArray( );
  1847       }
  1848  
  1849  
  1850       /*
  1851        * Enc rypt the c ontents us ing Passwo rd-based ( PBE) encry ption
  1852        * as  defined in  PKCS #5.
  1853        *
  1854        * NOT E: Current ly pbeWith SHAAnd40Bi teRC2-CBC  algorithmI D is used
  1855        *        to deri ve the key  and IV.
  1856        *
  1857        * @re turn encry pted conte nts encode d as Encry ptedConten tInfo
  1858        */
  1859       privat e byte[] e ncryptCont ent(byte[]  data, cha r[] passwo rd)
  1860           th rows IOExc eption {
  1861  
  1862           by te[] encry ptedData =  null;
  1863  
  1864           //  create Al gorithmPar ameters
  1865           Al gorithmPar ameters al gParams =
  1866                    getP BEAlgorith mParameter s("PBEWith SHA1AndRC2 _40");
  1867           De rOutputStr eam bytes  = new DerO utputStrea m();
  1868           Al gorithmId  algId =
  1869                    new  AlgorithmI d(pbeWithS HAAnd40Bit RC2CBC_OID , algParam s);
  1870           al gId.encode (bytes);
  1871           by te[] encod edAlgId =  bytes.toBy teArray();
  1872  
  1873           tr y {
  1874                // Use J CE
  1875                SecretKe y skey = g etPBEKey(p assword);
  1876                Cipher c ipher = Ci pher.getIn stance("PB EWithSHA1A ndRC2_40") ;
  1877                cipher.i nit(Cipher .ENCRYPT_M ODE, skey,  algParams );
  1878                encrypte dData = ci pher.doFin al(data);
  1879  
  1880                if (debu g != null)  {
  1881                    debu g.println( "  (Cipher  algorithm : " + ciph er.getAlgo rithm() +
  1882                         ")");
  1883                }
  1884  
  1885           }  catch (Exc eption e)  {
  1886                throw ne w IOExcept ion("Faile d to encry pt" +
  1887                         " safe con tents entr y: " + e,  e);
  1888           }
  1889  
  1890           //  create En cryptedCon tentInfo
  1891           De rOutputStr eam bytes2  = new Der OutputStre am();
  1892           by tes2.putOI D(ContentI nfo.DATA_O ID);
  1893           by tes2.write (encodedAl gId);
  1894  
  1895           //  Wrap encr ypted data  in a cont ext-specif ic tag.
  1896           De rOutputStr eam tmpout 2 = new De rOutputStr eam();
  1897           tm pout2.putO ctetString (encrypted Data);
  1898           by tes2.write Implicit(D erValue.cr eateTag(De rValue.TAG _CONTEXT,
  1899                                               false, (by te)0), tmp out2);
  1900  
  1901           //  wrap Encr yptedConte ntInfo in  a Sequence
  1902           De rOutputStr eam out =  new DerOut putStream( );
  1903           ou t.write(De rValue.tag _Sequence,  bytes2);
  1904           re turn out.t oByteArray ();
  1905       }
  1906  
  1907       /**
  1908        * Loa ds the key store from  the given  input str eam.
  1909        *
  1910        * <p> If a passw ord is giv en, it is  used to ch eck the in tegrity of  the
  1911        * key store data . Otherwis e, the int egrity of  the keysto re is not  checked.
  1912        *
  1913        * @pa ram stream  the input  stream fr om which t he keystor e is loade d
  1914        * @pa ram passwo rd the (op tional) pa ssword use d to check  the integ rity of
  1915        * the  keystore.
  1916        *
  1917        * @ex ception IO Exception  if there i s an I/O o r format p roblem wit h the
  1918        * key store data
  1919        * @ex ception No SuchAlgori thmExcepti on if the  algorithm  used to ch eck
  1920        * the  integrity  of the ke ystore can not be fou nd
  1921        * @ex ception Ce rtificateE xception i f any of t he certifi cates in t he
  1922        * key store coul d not be l oaded
  1923        */
  1924       public  synchroni zed void e ngineLoad( InputStrea m stream,  char[] pas sword)
  1925           th rows IOExc eption, No SuchAlgori thmExcepti on, Certif icateExcep tion
  1926       {
  1927           Da taInputStr eam dis;
  1928           Ce rtificateF actory cf  = null;
  1929           By teArrayInp utStream b ais = null ;
  1930           by te[] encod ed = null;
  1931  
  1932           if  (stream = = null)
  1933               return;
  1934  
  1935           //  reset the  counter
  1936           co unter = 0;
  1937  
  1938           De rValue val  = new Der Value(stre am);
  1939           De rInputStre am s = val .toDerInpu tStream();
  1940           in t version  = s.getInt eger();
  1941  
  1942           if  (version  != VERSION _3) {
  1943               throw new  IOExcepti on("PKCS12  keystore  not in ver sion 3 for mat");
  1944           }
  1945  
  1946           en tries.clea r();
  1947  
  1948           /*
  1949            *  Read the  authSafe.
  1950            * /
  1951           by te[] authS afeData;
  1952           Co ntentInfo  authSafe =  new Conte ntInfo(s);
  1953           Ob jectIdenti fier conte ntType = a uthSafe.ge tContentTy pe();
  1954  
  1955           if  (contentT ype.equals ((Object)C ontentInfo .DATA_OID) ) {
  1956               authSafeD ata = auth Safe.getDa ta();
  1957           }  else /* si gned data  */ {
  1958               throw new  IOExcepti on("public  key prote cted PKCS1 2 not supp orted");
  1959           }
  1960  
  1961           De rInputStre am as = ne w DerInput Stream(aut hSafeData) ;
  1962           De rValue[] s afeContent sArray = a s.getSeque nce(2);
  1963           in t count =  safeConten tsArray.le ngth;
  1964  
  1965           //  reset the  counters  at the sta rt
  1966           pr ivateKeyCo unt = 0;
  1967             PW      KeyCount =  0;
  1968           ce rtificateC ount = 0;
  1969  
  1970           /*
  1971            *  Spin over  the Conte ntInfos.
  1972            * /
  1973           fo r (int i =  0; i < co unt; i++)  {
  1974                byte[] s afeContent sData;
  1975                ContentI nfo safeCo ntents;
  1976                DerInput Stream sci ;
  1977                byte[] e AlgId = nu ll;
  1978  
  1979                sci = ne w DerInput Stream(saf eContentsA rray[i].to ByteArray( ));
  1980                safeCont ents = new  ContentIn fo(sci);
  1981                contentT ype = safe Contents.g etContentT ype();
  1982                safeCont entsData =  null;
  1983                if (cont entType.eq uals((Obje ct)Content Info.DATA_ OID)) {
  1984  
  1985                    if ( debug != n ull) {
  1986                         debug.prin tln("Loadi ng PKCS#7  data");
  1987                    }
  1988  
  1989                    safe ContentsDa ta = safeC ontents.ge tData();
  1990                } else i f (content Type.equal s((Object) ContentInf o.ENCRYPTE D_DATA_OID )) {
  1991                    if ( password = = null) {
  1992  
  1993                         if (debug  != null) {
  1994                             debug. println("W arning: sk ipping PKC S#7 encryp tedData" +
  1995                                 "  - no passw ord was su pplied");
  1996                         }
  1997                         continue;
  1998                    }
  1999  
  2000                    DerI nputStream  edi =
  2001                                      safeCont ents.getCo ntent().to DerInputSt ream();
  2002                    int  edVersion  = edi.getI nteger();
  2003                    DerV alue[] seq  = edi.get Sequence(2 );
  2004                    Obje ctIdentifi er edConte ntType = s eq[0].getO ID();
  2005                    eAlg Id = seq[1 ].toByteAr ray();
  2006                    if ( !seq[2].is ContextSpe cific((byt e)0)) {
  2007                       t hrow new I OException ("encrypte d content  not presen t!");
  2008                    }
  2009                    byte  newTag =  DerValue.t ag_OctetSt ring;
  2010                    if ( seq[2].isC onstructed ())
  2011                       n ewTag |= 0 x20;
  2012                    seq[ 2].resetTa g(newTag);
  2013                    safe ContentsDa ta = seq[2 ].getOctet String();
  2014  
  2015                    // p arse Algor ithm param eters
  2016                    DerI nputStream  in = seq[ 1].toDerIn putStream( );
  2017                    Obje ctIdentifi er algOid  = in.getOI D();
  2018                    Algo rithmParam eters algP arams = pa rseAlgPara meters(alg Oid, in);
  2019  
  2020                    PBEP arameterSp ec pbeSpec ;
  2021                    int  ic = 0;
  2022  
  2023                    if ( algParams  != null) {
  2024                         try {
  2025                             pbeSpe c =
  2026                                 al gParams.ge tParameter Spec(PBEPa rameterSpe c.class);
  2027                         } catch (I nvalidPara meterSpecE xception i pse) {
  2028                             throw  new IOExce ption(
  2029                                 "I nvalid PBE  algorithm  parameter s");
  2030                         }
  2031                         ic = pbeSp ec.getIter ationCount ();
  2032  
  2033                         if (ic > M AX_ITERATI ON_COUNT)  {
  2034                             throw  new IOExce ption("PBE  iteration  count too  large");
  2035                         }
  2036                    }
  2037  
  2038                    if ( debug != n ull) {
  2039                         debug.prin tln("Loadi ng PKCS#7  encryptedD ata " +
  2040                             "(" +  new Algori thmId(algO id).getNam e() +
  2041                             " iter ations: "  + ic + ")" );
  2042                    }
  2043  
  2044                    whil e (true) {
  2045                         try {
  2046                             // Use  JCE
  2047                             Secret Key skey =  getPBEKey (password) ;
  2048                             Cipher  cipher =  Cipher.get Instance(a lgOid.toSt ring());
  2049                             cipher .init(Ciph er.DECRYPT _MODE, ske y, algPara ms);
  2050                             safeCo ntentsData  = cipher. doFinal(sa feContents Data);
  2051                             break;
  2052                         } catch (E xception e ) {
  2053                             if (pa ssword.len gth == 0)  {
  2054                                 //  Retry usi ng an empt y password
  2055                                 //  without a  NULL term inator.
  2056                                 pa ssword = n ew char[1] ;
  2057                                 co ntinue;
  2058                             }
  2059                             throw  new IOExce ption("key store pass word was i ncorrect",
  2060                                 ne w Unrecove rableKeyEx ception(
  2061                                      "failed  to decrypt  safe cont ents entry : " + e));
  2062                         }
  2063                    }
  2064                } else {
  2065                    thro w new IOEx ception("p ublic key  protected  PKCS12" +
  2066                                               " not supp orted");
  2067                }
  2068                DerInput Stream sc  = new DerI nputStream (safeConte ntsData);
  2069                loadSafe Contents(s c, passwor d);
  2070           }
  2071  
  2072           //  The MacDa ta is opti onal.
  2073           if  (password  != null & & s.availa ble() > 0)  {
  2074                MacData  macData =  new MacDat a(s);
  2075                int ic =  macData.g etIteratio ns();
  2076  
  2077                try {
  2078                    if ( ic > MAX_I TERATION_C OUNT) {
  2079                         throw new  InvalidAlg orithmPara meterExcep tion(
  2080                             "MAC i teration c ount too l arge: " +  ic);
  2081                    }
  2082  
  2083                    Stri ng algName  =
  2084                             macDat a.getDiges tAlgName() .toUpperCa se(Locale. ENGLISH);
  2085  
  2086                    // C hange SHA- 1 to SHA1
  2087                    algN ame = algN ame.replac e("-", "") ;
  2088  
  2089                    // g enerate MA C (MAC key  is create d within J CE)
  2090                    Mac  m = Mac.ge tInstance( "HmacPBE"  + algName) ;
  2091                    PBEP arameterSp ec params  =
  2092                             new PB EParameter Spec(macDa ta.getSalt (), ic);
  2093                    Secr etKey key  = getPBEKe y(password );
  2094                    m.in it(key, pa rams);
  2095                    m.up date(authS afeData);
  2096                    byte [] macResu lt = m.doF inal();
  2097  
  2098                    if ( debug != n ull) {
  2099                         debug.prin tln("Check ing keysto re integri ty " +
  2100                             "(" +  m.getAlgor ithm() + "  iteration s: " + ic  + ")");
  2101                    }
  2102  
  2103                    if ( !MessageDi gest.isEqu al(macData .getDigest (), macRes ult)) {
  2104                       t hrow new U nrecoverab leKeyExcep tion("Fail ed PKCS12"  +
  2105                                               " integrit y checking ");
  2106                    }
  2107                } catch  (Exception  e) {
  2108                    thro w new IOEx ception("I ntegrity c heck faile d: " + e,  e);
  2109                }
  2110           }
  2111  
  2112           /*
  2113            *  Match up  private ke ys with ce rtificate  chains.
  2114            * /
  2115           Pr ivateKeyEn try[] list  =
  2116                keyList. toArray(ne w PrivateK eyEntry[ke yList.size ()]);
  2117           fo r (int m =  0; m < li st.length;  m++) {
  2118                PrivateK eyEntry en try = list [m];
  2119                if (entr y.keyId !=  null) {
  2120                    Arra yList<X509 Certificat e> chain =
  2121                                      new Arra yList<X509 Certificat e>();
  2122                    X509 Certificat e cert = f indMatched Certificat e(entry);
  2123  
  2124                    main loop:
  2125                    whil e (cert !=  null) {
  2126                         // Check f or loops i n the cert ificate ch ain
  2127                         if (!chain .isEmpty() ) {
  2128                             for (X 509Certifi cate chain Cert : cha in) {
  2129                                 if  (cert.equ als(chainC ert)) {
  2130                                      if (debu g != null)  {
  2131                                          debu g.println( "Loop dete cted in "  +
  2132                                               "certifica te chain.  Skip addin g " +
  2133                                               "repeated  cert to ch ain. Subje ct: " +
  2134                                               cert.getSu bjectX500P rincipal()
  2135                                                   .toStr ing());
  2136                                      }
  2137                                      break ma inloop;
  2138                                 }
  2139                             }
  2140                         }
  2141                         chain.add( cert);
  2142                         X500Princi pal issuer DN = cert. getIssuerX 500Princip al();
  2143                         if (issuer DN.equals( cert.getSu bjectX500P rincipal() )) {
  2144                             break;
  2145                         }
  2146                         cert = cer tsMap.get( issuerDN);
  2147                    }
  2148                    /* U pdate exis ting KeyEn try in ent ries table  */
  2149                    if ( chain.size () > 0)
  2150                         entry.chai n = chain. toArray(ne w Certific ate[chain. size()]);
  2151                }
  2152           }
  2153  
  2154           if  (debug !=  null) {
  2155                if (priv ateKeyCoun t > 0) {
  2156                    debu g.println( "Loaded "  + privateK eyCount +
  2157                         " protecte d private  key(s)");
  2158                }
  2159                  if ( PW      KeyCount >  0) {
  2160                      debug.prin tln("Loade d " +  PW      KeyCount +
  2161                          " protecte PW        key(s)");
  2162                }
  2163                if (cert ificateCou nt > 0) {
  2164                    debu g.println( "Loaded "  + certific ateCount +
  2165                         " certific ate(s)");
  2166                }
  2167           }
  2168  
  2169           ce rtEntries. clear();
  2170           ce rtsMap.cle ar();
  2171           ke yList.clea r();
  2172       }
  2173  
  2174       /**
  2175        * Loc ates a mat ched CertE ntry from  certEntrie s, and ret urns its c ert.
  2176        * @pa ram entry  the KeyEnt ry to matc h
  2177        * @re turn a cer tificate,  null if no t found
  2178        */
  2179       privat e X509Cert ificate fi ndMatchedC ertificate (PrivateKe yEntry ent ry) {
  2180           Ce rtEntry ke yIdMatch =  null;
  2181           Ce rtEntry al iasMatch =  null;
  2182           fo r (CertEnt ry ce: cer tEntries)  {
  2183                if (Arra ys.equals( entry.keyI d, ce.keyI d)) {
  2184                    keyI dMatch = c e;
  2185                    if ( entry.alia s.equalsIg noreCase(c e.alias))  {
  2186                         // Full ma tch!
  2187                         return ce. cert;
  2188                    }
  2189                } else i f (entry.a lias.equal sIgnoreCas e(ce.alias )) {
  2190                    alia sMatch = c e;
  2191                }
  2192           }
  2193           //  keyId mat ch first,  for compat ibility
  2194           if  (keyIdMat ch != null ) return k eyIdMatch. cert;
  2195           el se if (ali asMatch !=  null) ret urn aliasM atch.cert;
  2196           el se return  null;
  2197       }
  2198  
  2199       privat e void loa dSafeConte nts(DerInp utStream s tream, cha r[] passwo rd)
  2200           th rows IOExc eption, No SuchAlgori thmExcepti on, Certif icateExcep tion
  2201       {
  2202           De rValue[] s afeBags =  stream.get Sequence(2 );
  2203           in t count =  safeBags.l ength;
  2204  
  2205           /*
  2206            *  Spin over  the SafeB ags.
  2207            * /
  2208           fo r (int i =  0; i < co unt; i++)  {
  2209                ObjectId entifier b agId;
  2210                DerInput Stream sbi ;
  2211                DerValue  bagValue;
  2212                Object b agItem = n ull;
  2213  
  2214                sbi = sa feBags[i]. toDerInput Stream();
  2215                bagId =  sbi.getOID ();
  2216                bagValue  = sbi.get DerValue() ;
  2217                if (!bag Value.isCo ntextSpeci fic((byte) 0)) {
  2218                    thro w new IOEx ception("u nsupported  PKCS12 ba g value ty pe "
  2219                                               + bagValue .tag);
  2220                }
  2221                bagValue  = bagValu e.data.get DerValue() ;
  2222                if (bagI d.equals(( Object)PKC S8Shrouded KeyBag_OID )) {
  2223                    Priv ateKeyEntr y kEntry =  new Priva teKeyEntry ();
  2224                    kEnt ry.protect edPrivKey  = bagValue .toByteArr ay();
  2225                    bagI tem = kEnt ry;
  2226                    priv ateKeyCoun t++;
  2227                } else i f (bagId.e quals((Obj ect)CertBa g_OID)) {
  2228                    DerI nputStream  cs = new  DerInputSt ream(bagVa lue.toByte Array());
  2229                    DerV alue[] cer tValues =  cs.getSequ ence(2);
  2230                    Obje ctIdentifi er certId  = certValu es[0].getO ID();
  2231                    if ( !certValue s[1].isCon textSpecif ic((byte)0 )) {
  2232                         throw new  IOExceptio n("unsuppo rted PKCS1 2 cert val ue type "
  2233                                               + certValu es[1].tag) ;
  2234                    }
  2235                    DerV alue certV alue = cer tValues[1] .data.getD erValue();
  2236                    Cert ificateFac tory cf =  Certificat eFactory.g etInstance ("X509");
  2237                    X509 Certificat e cert;
  2238                    cert  = (X509Ce rtificate) cf.generat eCertifica te
  2239                             (new B yteArrayIn putStream( certValue. getOctetSt ring()));
  2240                    bagI tem = cert ;
  2241                    cert ificateCou nt++;
  2242                } else i f (bagId.e quals((Obj ect)Secret Bag_OID))  {
  2243                    DerI nputStream  ss = new  DerInputSt ream(bagVa lue.toByte Array());
  2244                      DerValue[]   PW      Values = s s.getSeque nce(2);
  2245                      ObjectIden tifier  PW      Id =  PW      Values[0]. getOID();
  2246                      if (! PW      Values[1]. isContextS pecific((b yte)0)) {
  2247                         throw new  IOExceptio n(
  2248                               "unsupport ed PKCS12  PW        value type  "
  2249                                                PW      Values[1]. tag);
  2250                    }
  2251                      DerValue  PW      Value =  PW      Values[1]. data.getDe rValue();
  2252                    Secr etKeyEntry  kEntry =  new Secret KeyEntry() ;
  2253                      kEntry.pro tectedSecr etKey =  PW      Value.getO ctetString ();
  2254                    bagI tem = kEnt ry;
  2255                      PW      KeyCount++ ;
  2256                } else {
  2257  
  2258                    if ( debug != n ull) {
  2259                         debug.prin tln("Unsup ported PKC S12 bag ty pe: " + ba gId);
  2260                    }
  2261                }
  2262  
  2263                DerValue [] attrSet ;
  2264                try {
  2265                    attr Set = sbi. getSet(3);
  2266                } catch  (IOExcepti on e) {
  2267                    // e ntry does  not have a ttributes
  2268                    // N ote: CA ce rts can ha ve no attr ibutes
  2269                    // O penSSL gen erates pkc s12 with n o attr for  CA certs.
  2270                    attr Set = null ;
  2271                }
  2272  
  2273                String a lias = nul l;
  2274                byte[] k eyId = nul l;
  2275                ObjectId entifier[]  trustedKe yUsage = n ull;
  2276                Set<PKCS 12Attribut e> attribu tes = new  HashSet<>( );
  2277  
  2278                if (attr Set != nul l) {
  2279                    for  (int j = 0 ; j < attr Set.length ; j++) {
  2280                         byte[] enc oded = att rSet[j].to ByteArray( );
  2281                         DerInputSt ream as =  new DerInp utStream(e ncoded);
  2282                         DerValue[]  attrSeq =  as.getSeq uence(2);
  2283                         ObjectIden tifier att rId = attr Seq[0].get OID();
  2284                         DerInputSt ream vs =
  2285                             new De rInputStre am(attrSeq [1].toByte Array());
  2286                         DerValue[]  valSet;
  2287                         try {
  2288                             valSet  = vs.getS et(1);
  2289                         } catch (I OException  e) {
  2290                             throw  new IOExce ption("Att ribute " +  attrId +
  2291                                      " should  have a va lue " + e. getMessage ());
  2292                         }
  2293                         if (attrId .equals((O bject)PKCS 9FriendlyN ame_OID))  {
  2294                             alias  = valSet[0 ].getBMPSt ring();
  2295                         } else if  (attrId.eq uals((Obje ct)PKCS9Lo calKeyId_O ID)) {
  2296                             keyId  = valSet[0 ].getOctet String();
  2297                         } else if
  2298                             (attrI d.equals(( Object)Tru stedKeyUsa ge_OID)) {
  2299                             truste dKeyUsage  = new Obje ctIdentifi er[valSet. length];
  2300                             for (i nt k = 0;  k < valSet .length; k ++) {
  2301                                 tr ustedKeyUs age[k] = v alSet[k].g etOID();
  2302                             }
  2303                         } else {
  2304                             attrib utes.add(n ew PKCS12A ttribute(e ncoded));
  2305                         }
  2306                    }
  2307                }
  2308  
  2309                /*
  2310                 * As pe r PKCS12 v 1.0 friend lyname (al ias) and l ocalKeyId  (keyId)
  2311                 * are o ptional PK CS12 bagAt tributes.  But entrie s in the k eyStore
  2312                 * are i dentified  by their a lias. Henc e we need  to have an
  2313                 * Unfri endlyname  in the ali as, if ali as is null . The keyI d
  2314                 * attri bute is re quired to  match the  private ke y with the
  2315                 * certi ficate. If  we get a  bagItem of  type KeyE ntry with  a
  2316                 * null  keyId, we  should ski p it entir ely.
  2317                 */
  2318                if (bagI tem instan ceof KeyEn try) {
  2319                    KeyE ntry entry  = (KeyEnt ry)bagItem ;
  2320  
  2321                    if ( bagItem in stanceof P rivateKeyE ntry) {
  2322                         if (keyId  == null) {
  2323                            // Inse rt a local KeyID for  the privat eKey
  2324                            // Note : This is  a workarou nd to allo w null loc alKeyID
  2325                            // attr ibute in p kcs12 with  one priva te key ent ry and
  2326                            // asso ciated cer t-chain
  2327                            if (pri vateKeyCou nt == 1) {
  2328                                 ke yId = "01" .getBytes( "UTF8");
  2329                            } else  {
  2330                                 co ntinue;
  2331                            }
  2332                         }
  2333                    }
  2334                    entr y.keyId =  keyId;
  2335                    // r estore dat e if it ex ists
  2336                    Stri ng keyIdSt r = new St ring(keyId , "UTF8");
  2337                    Date  date = nu ll;
  2338                    if ( keyIdStr.s tartsWith( "Time "))  {
  2339                         try {
  2340                             date =  new Date(
  2341                                      Long.par seLong(key IdStr.subs tring(5))) ;
  2342                         } catch (E xception e ) {
  2343                             date =  null;
  2344                         }
  2345                    }
  2346                    if ( date == nu ll) {
  2347                         date = new  Date();
  2348                    }
  2349                    entr y.date = d ate;
  2350  
  2351                    if ( bagItem in stanceof P rivateKeyE ntry) {
  2352                         keyList.ad d((Private KeyEntry)  entry);
  2353                    }
  2354                    if ( entry.attr ibutes ==  null) {
  2355                         entry.attr ibutes = n ew HashSet <>();
  2356                    }
  2357                    entr y.attribut es.addAll( attributes );
  2358                    if ( alias == n ull) {
  2359                       a lias = get Unfriendly Name();
  2360                    }
  2361                    entr y.alias =  alias;
  2362                    entr ies.put(al ias.toLowe rCase(Loca le.ENGLISH ), entry);
  2363  
  2364                } else i f (bagItem  instanceo f X509Cert ificate) {
  2365                    X509 Certificat e cert = ( X509Certif icate)bagI tem;
  2366                    // I nsert a lo calKeyID f or the cor responding  cert
  2367                    // N ote: This  is a worka round to a llow null  localKeyID
  2368                    // a ttribute i n pkcs12 w ith one pr ivate key  entry and
  2369                    // a ssociated  cert-chain
  2370                    if ( (keyId ==  null) && ( privateKey Count == 1 )) {
  2371                         // insert  localKeyID  only for  EE cert or  self-sign ed cert
  2372                         if (i == 0 ) {
  2373                             keyId  = "01".get Bytes("UTF 8");
  2374                         }
  2375                    }
  2376                    // T rusted cer tificate
  2377                    if ( trustedKey Usage != n ull) {
  2378                         if (alias  == null) {
  2379                             alias  = getUnfri endlyName( );
  2380                         }
  2381                         CertEntry  certEntry  =
  2382                             new Ce rtEntry(ce rt, keyId,  alias, tr ustedKeyUs age,
  2383                                 at tributes);
  2384                         entries.pu t(alias.to LowerCase( Locale.ENG LISH), cer tEntry);
  2385                    } el se {
  2386                         certEntrie s.add(new  CertEntry( cert, keyI d, alias)) ;
  2387                    }
  2388                    X500 Principal  subjectDN  = cert.get SubjectX50 0Principal ();
  2389                    if ( subjectDN  != null) {
  2390                         if (!certs Map.contai nsKey(subj ectDN)) {
  2391                             certsM ap.put(sub jectDN, ce rt);
  2392                         }
  2393                    }
  2394                }
  2395           }
  2396       }
  2397  
  2398       privat e String g etUnfriend lyName() {
  2399           co unter++;
  2400           re turn (Stri ng.valueOf (counter)) ;
  2401       }
  2402   }