1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /** 19 * @author Alexander V. Astapchuk 20 */ 21 22 package org.apache.harmony.security.tests.support; 23 24 import java.io.IOException; 25 import java.io.InputStream; 26 import java.io.ObjectInputStream; 27 import java.io.ObjectOutputStream; 28 import java.io.Serializable; 29 import java.io.StreamCorruptedException; 30 import java.math.BigInteger; 31 32 import java.security.InvalidKeyException; 33 import java.security.NoSuchAlgorithmException; 34 import java.security.NoSuchProviderException; 35 import java.security.Principal; 36 import java.security.Provider; 37 import java.security.PublicKey; 38 import java.security.Security; 39 import java.security.SignatureException; 40 41 import java.security.cert.*; 42 import java.util.*; 43 44 import javax.security.auth.x500.X500Principal; 45 46 /** 47 * The class contains various utility methods used during the java.security 48 * classes testing. 49 * 50 */ 51 52 public final class TestCertUtils { 53 TestCertUtils()54 private TestCertUtils() { 55 throw new Error("statics only"); 56 } 57 58 /** 59 * Returns new instance of test certificate each time the method is called. 60 * 61 * @return test certificate 62 */ getCert()63 public static Certificate getCert() { 64 return new TestCertificate(); 65 } 66 67 /** 68 * Returns an array of 3 test certificates. IMP: The array returned is not 69 * real chain of certificates, it's just an array of 3 certs. The method 70 * returns new array each time it's called. The number of 3 was chosen 71 * arbitrarily and is subject to change. 72 * 73 * @return an array of 3 certificates 74 */ getCertChain()75 public static Certificate[] getCertChain() { 76 Certificate[] chain = { new TestCertificate(), new TestCertificate(), 77 new TestCertificate() }; 78 return chain; 79 } 80 81 /** 82 * Returns a test CertPath, which uses getCertChain() to obtain a list of 83 * certificates to store. 84 * 85 * @return test cert path 86 */ getCertPath()87 public static CertPath getCertPath() { 88 return new TestCertPath(); 89 } 90 91 /** 92 * Generates and returns an instance of TestCertPath.<br> 93 * TestCertificate-s included in the CertPath will be uniq (will have 94 * different numbers passed to their ctor-s).<br> 95 * The second arguments shows which number will have the first Certificate 96 * in the CertPath. The second certificate will have (startID+1) number 97 * and so on. 98 * 99 * @param howMany - shows how many TestCerts must contain the CertPath generated 100 * @param startID - specifies the starting ID which the first certificate will have 101 * @return TestCertPath 102 */ genCertPath(int howMany, int startID)103 public static CertPath genCertPath(int howMany, int startID) { 104 Certificate[] certs = new Certificate[howMany]; 105 for (int i = 0; i < howMany; i++) { 106 certs[i] = new TestCertificate(Integer.toString(startID + i)); 107 } 108 return new TestCertPath(certs); 109 } 110 111 private static Provider provider = null; 112 113 private static final String providerName = "TstPrvdr"; 114 115 /** 116 * A Principal used to form rootCA's certificate 117 */ 118 public static final X500Principal rootPrincipal = new X500Principal( 119 UniGen.rootName); 120 121 /** 122 * Some fake rootCA's certificate. 123 */ 124 public static final X509Certificate rootCA = new TestX509Certificate( 125 rootPrincipal, rootPrincipal); 126 install_test_x509_factory()127 public static void install_test_x509_factory() { 128 if (provider == null) { 129 provider = new TestProvider(providerName, 0.01, 130 "Test provider for serialization testing"); 131 Security.insertProviderAt(provider, 1); 132 } 133 } 134 uninstall_test_x509_factory()135 public static void uninstall_test_x509_factory() { 136 if (provider != null) { 137 Security.removeProvider(providerName); 138 provider = null; 139 } 140 } 141 142 /** 143 * The class represents test certificate path. 144 * 145 */ 146 147 public static final class TestCertPath extends CertPath implements 148 Serializable { 149 150 private static final byte[] encoded = new byte[] { 1, 2, 3, 4, 5, 6, 7, 151 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; 152 153 private static final String serializedData = "Just a dummy string to be serialized instead of real data"; 154 155 private Certificate[] certs; 156 157 /** 158 * Default ctor for TestCertPath. Uses {@link TestCertUtils#getCertChain()} 159 * to obtain list of certificates.<br> 160 * All TestCertPath-s constructed via this ctor will be equals() to each 161 * other. 162 */ TestCertPath()163 public TestCertPath() { 164 super("testCertPath"); 165 certs = getCertChain(); 166 } 167 168 /** 169 * Constructs TestCertPath and keeps the given array of certificates.<br> 170 * The TestCertPaths constructed via this ctor may be different (if they 171 * have different set of certificates)<br> 172 * @see TestCertUtils#genCertPath(int, int) 173 * @param certs 174 */ TestCertPath(Certificate[] certs)175 public TestCertPath(Certificate[] certs) { 176 super("testCertPath"); 177 this.certs = certs; 178 } 179 180 /** 181 * @see java.security.cert.CertPath#getCertificates() 182 */ getCertificates()183 public List getCertificates() { 184 return Arrays.asList(certs); 185 } 186 187 /** 188 * @see java.security.cert.CertPath#getEncoded() 189 */ getEncoded()190 public byte[] getEncoded() throws CertificateEncodingException { 191 return encoded.clone(); 192 } 193 194 /** 195 * @see java.security.cert.CertPath#getEncoded(java.lang.String) 196 */ getEncoded(String encoding)197 public byte[] getEncoded(String encoding) 198 throws CertificateEncodingException { 199 return encoded.clone(); 200 } 201 202 /** 203 * @see java.security.cert.CertPath#getEncodings() 204 */ getEncodings()205 public Iterator getEncodings() { 206 Vector v = new Vector(); 207 v.add("myTestEncoding"); 208 return v.iterator(); 209 } 210 toString()211 public String toString() { 212 StringBuffer buf = new StringBuffer(200); 213 buf.append("TestCertPath. certs count="); 214 if( certs == null ) { 215 buf.append("0\n"); 216 } 217 else { 218 buf.append(certs.length).append("\n"); 219 for( int i=0; i<certs.length; i++) { 220 buf.append("\t").append(i).append(" "); 221 buf.append(certs[i]).append("\n"); 222 } 223 } 224 return buf.toString(); 225 } 226 227 /** 228 * Writes<br> 229 * (String) serializedData<br> 230 * (int) number of certificates in this CertPath<br> 231 * <array of certificates> 232 * 233 * @param out 234 * @throws IOException 235 */ writeObject(ObjectOutputStream out)236 private void writeObject(ObjectOutputStream out) throws IOException { 237 out.writeUTF(serializedData); 238 if (certs == null) { 239 out.writeInt(0); 240 } else { 241 out.writeInt(certs.length); 242 for (int i = 0; i < certs.length; i++) { 243 out.writeObject(certs[i]); 244 } 245 } 246 } 247 readObject(ObjectInputStream in)248 private void readObject(ObjectInputStream in) throws IOException, 249 ClassNotFoundException { 250 String s = in.readUTF(); 251 if (!serializedData.equals(s)) { 252 throw new StreamCorruptedException("expect [" + serializedData 253 + "] got [" + s + "]"); 254 } 255 int count = in.readInt(); 256 certs = new Certificate[count]; 257 for (int i = 0; i < count; i++) { 258 certs[i] = (Certificate) in.readObject(); 259 } 260 } 261 writeReplace()262 protected Object writeReplace() { 263 return this; 264 } 265 readResolve()266 protected Object readResolve() { 267 return this; 268 } 269 } 270 271 /** 272 * The class represents empty PublicKey. 273 * 274 */ 275 276 public static final class TestPublicKey implements PublicKey { 277 private static final String algo = "testPublicKeyAlgorithm"; 278 279 private static final byte[] encoded = new byte[] { 1, 2, 3, 4, 5, 6, 7, 280 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; 281 282 private static final String format = "testPublicKeyFormat"; 283 getAlgorithm()284 public String getAlgorithm() { 285 return algo; 286 } 287 getEncoded()288 public byte[] getEncoded() { 289 return encoded.clone(); 290 } 291 getFormat()292 public String getFormat() { 293 return format; 294 } 295 } 296 297 /** 298 * The class represents test certificate. 299 * 300 */ 301 302 public static class TestCertificate extends Certificate implements 303 Serializable { 304 305 private static final byte[] encoded = new byte[] { 1, 2, 3, 4, 5, 6, 7, 306 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; 307 308 public static final String TYPE = "Test"; 309 310 // 311 // A String that makes different TestCertificates to be different. 312 // 313 private String diff = null; 314 315 /** 316 * Default ctor. All the TestCertificate-s created with this ctor are equals() to each other. 317 * Use TestCertificate(String) if you need non equal TestCertificate-s. 318 */ TestCertificate()319 public TestCertificate() { 320 super(TYPE); 321 } 322 323 /** 324 * A special purpose ctor. Pass different String-s to have different TestCertificates. 325 * TestCertificate-s with the same String passed to this ctor are considered equal. 326 */ TestCertificate(String diff)327 public TestCertificate(String diff) { 328 super(TYPE); 329 this.diff = diff; 330 } 331 332 /** 333 * A ctor that allows to specify both the TYPE of certificate and the 334 * diff. Leave the <code>diff</code> null when no difference needed. 335 * 336 * @param diff 337 * @param type 338 */ TestCertificate(String diff, String type)339 public TestCertificate(String diff, String type) { 340 super(type); 341 this.diff = diff; 342 } 343 getEncoded()344 public byte[] getEncoded() throws CertificateEncodingException { 345 return encoded.clone(); 346 } 347 verify(PublicKey key)348 public void verify(PublicKey key) throws CertificateException, 349 NoSuchAlgorithmException, InvalidKeyException, 350 NoSuchProviderException, SignatureException { 351 // do nothing 352 } 353 verify(PublicKey key, String sigProvider)354 public void verify(PublicKey key, String sigProvider) 355 throws CertificateException, NoSuchAlgorithmException, 356 InvalidKeyException, NoSuchProviderException, 357 SignatureException { 358 // do nothing 359 360 } 361 toString()362 public String toString() { 363 return "Test certificate - for unit testing only"; 364 } 365 equals(Object obj)366 public boolean equals(Object obj) { 367 if (obj == null || !(obj instanceof TestCertificate)) { 368 return false; 369 } 370 TestCertificate that = (TestCertificate) obj; 371 if (this == that) { 372 return true; 373 } 374 if (this.diff == null) { 375 return that.diff == null; 376 } 377 return this.diff.equals(that.diff); 378 } 379 getPublicKey()380 public PublicKey getPublicKey() { 381 return new TestPublicKey(); 382 } 383 384 /** 385 * Writes:<br> 386 * boolean - true if this certificate has a diff string, 387 * false otherwise, followed by <br> 388 * writeUTF() of string (if presented) 389 * 390 * @param out 391 * @throws IOException 392 */ writeObject(ObjectOutputStream out)393 private void writeObject(ObjectOutputStream out) throws IOException { 394 if (diff == null) { 395 out.writeBoolean(false); 396 } else { 397 out.writeBoolean(false); 398 out.writeUTF(diff); 399 } 400 } 401 readObject(ObjectInputStream in)402 private void readObject(ObjectInputStream in) throws IOException, 403 ClassNotFoundException { 404 boolean hasDiffString = in.readBoolean(); 405 if (hasDiffString) { 406 diff = in.readUTF(); 407 } 408 } 409 writeReplace()410 protected Object writeReplace() { 411 return this; 412 } 413 readResolve()414 protected Object readResolve() { 415 return this; 416 } 417 } 418 419 public static class TestInvalidX509Certificate extends TestX509Certificate { TestInvalidX509Certificate(X500Principal subj, X500Principal issuer)420 public TestInvalidX509Certificate(X500Principal subj, 421 X500Principal issuer) { 422 super(subj, issuer); 423 } 424 } 425 426 /** 427 * 428 * TestX509CErtificate.<br> 429 * Does nothing interesting, but<br> 430 * a) is not abstract, so it can be instantiated<br> 431 * b) returns Encoded form<br> 432 * 433 */ 434 public static class TestX509Certificate extends X509Certificate { 435 private X500Principal subject; 436 437 private X500Principal issuer; 438 TestX509Certificate(X500Principal subj, X500Principal issuer)439 public TestX509Certificate(X500Principal subj, X500Principal issuer) { 440 this.subject = subj; 441 this.issuer = issuer; 442 } 443 getIssuerX500Principal()444 public X500Principal getIssuerX500Principal() { 445 return issuer; 446 } 447 getSubjectX500Principal()448 public X500Principal getSubjectX500Principal() { 449 return subject; 450 } 451 452 /** 453 * The encoded for of this X509Certificate is a byte array where 454 * first are bytes of encoded form of Subject (as X500Principal), 455 * followed by one zero byte 456 * and followed by the encoded form of Issuer (as X500Principal) 457 * 458 */ getEncoded()459 public byte[] getEncoded() throws CertificateEncodingException { 460 byte[] asubj = subject.getEncoded(); 461 byte[] aissuer = issuer.getEncoded(); 462 byte[] data = new byte[asubj.length + aissuer.length + 1]; 463 464 System.arraycopy(asubj, 0, data, 0, asubj.length); 465 //data[asubj.length] = 0; 466 System 467 .arraycopy(aissuer, 0, data, asubj.length + 1, 468 aissuer.length); 469 return data; 470 } 471 checkValidity()472 public void checkValidity() throws CertificateExpiredException, 473 CertificateNotYetValidException { 474 } 475 checkValidity(Date date)476 public void checkValidity(Date date) 477 throws CertificateExpiredException, 478 CertificateNotYetValidException { 479 } 480 getBasicConstraints()481 public int getBasicConstraints() { 482 return 0; 483 } 484 getIssuerDN()485 public Principal getIssuerDN() { 486 return null; 487 } 488 getIssuerUniqueID()489 public boolean[] getIssuerUniqueID() { 490 return null; 491 } 492 getKeyUsage()493 public boolean[] getKeyUsage() { 494 return null; 495 } 496 getNotAfter()497 public Date getNotAfter() { 498 return null; 499 } 500 getNotBefore()501 public Date getNotBefore() { 502 return null; 503 } 504 getSerialNumber()505 public BigInteger getSerialNumber() { 506 return null; 507 } 508 getSigAlgName()509 public String getSigAlgName() { 510 return null; 511 } 512 getSigAlgOID()513 public String getSigAlgOID() { 514 return null; 515 } 516 getSigAlgParams()517 public byte[] getSigAlgParams() { 518 return null; 519 } 520 getSignature()521 public byte[] getSignature() { 522 return null; 523 } 524 getSubjectDN()525 public Principal getSubjectDN() { 526 return null; 527 } 528 getSubjectUniqueID()529 public boolean[] getSubjectUniqueID() { 530 return null; 531 } 532 getTBSCertificate()533 public byte[] getTBSCertificate() throws CertificateEncodingException { 534 return null; 535 } 536 getVersion()537 public int getVersion() { 538 return 0; 539 } 540 getCriticalExtensionOIDs()541 public Set getCriticalExtensionOIDs() { 542 return null; 543 } 544 getExtensionValue(String oid)545 public byte[] getExtensionValue(String oid) { 546 return null; 547 } 548 getNonCriticalExtensionOIDs()549 public Set getNonCriticalExtensionOIDs() { 550 return null; 551 } 552 hasUnsupportedCriticalExtension()553 public boolean hasUnsupportedCriticalExtension() { 554 return false; 555 } 556 getPublicKey()557 public PublicKey getPublicKey() { 558 return null; 559 } 560 toString()561 public String toString() { 562 return null; 563 } 564 verify(PublicKey key, String sigProvider)565 public void verify(PublicKey key, String sigProvider) 566 throws CertificateException, NoSuchAlgorithmException, 567 InvalidKeyException, NoSuchProviderException, 568 SignatureException { 569 570 } 571 verify(PublicKey key)572 public void verify(PublicKey key) throws CertificateException, 573 NoSuchAlgorithmException, InvalidKeyException, 574 NoSuchProviderException, SignatureException { 575 576 } 577 } 578 579 /** 580 * TestProvider. Does nothing, but pretends to 581 * implement X.509 CertificateFactory. 582 */ 583 public static class TestProvider extends Provider { 584 585 private Provider.Service serv; 586 TestProvider(String name, double version, String info)587 public TestProvider(String name, double version, String info) { 588 super(name, version, info); 589 serv = new Provider.Service(this, "CertificateFactory", "X.509", 590 TestFactorySpi.class.getName(), new ArrayList(), null); 591 } 592 getServices()593 public synchronized Set getServices() { 594 HashSet s = new HashSet(); 595 s.add(serv); 596 return s; 597 } 598 } 599 600 /** 601 * Some kind of Certificate Factory, used during unit testing. 602 * 603 * 604 */ 605 public static class TestFactorySpi extends CertificateFactorySpi { 606 607 /** 608 * Tries to create an instance of TestX509Certificate, basing 609 * on the presumption that its {@link TestX509Certificate#getEncoded() 610 * encoded} form is stored.<br> 611 * @throws CertificateException is the presumption is not met or if 612 * any IO problem occurs. 613 */ engineGenerateCertificate(InputStream is)614 public Certificate engineGenerateCertificate(InputStream is) 615 throws CertificateException { 616 byte[] data = new byte[0]; 617 byte[] chunk = new byte[1024]; 618 int len; 619 try { 620 while ((len = is.read(chunk)) > 0) { 621 byte[] tmp = new byte[data.length + len]; 622 System.arraycopy(data, 0, tmp, 0, data.length); 623 System.arraycopy(chunk, 0, tmp, data.length, len); 624 data = tmp; 625 } 626 } catch (IOException ex) { 627 throw new CertificateException("IO problem", ex); 628 } 629 int pos = Arrays.binarySearch(data, (byte) 0); 630 if (pos < 0) { 631 throw new CertificateException("invalid format"); 632 } 633 byte[] subjNameData = new byte[pos]; 634 System.arraycopy(data, 0, subjNameData, 0, subjNameData.length); 635 byte[] issNameData = new byte[data.length - pos - 1]; 636 System.arraycopy(data, pos + 1, issNameData, 0, issNameData.length); 637 X500Principal subjName = new X500Principal(subjNameData); 638 X500Principal issName = new X500Principal(issNameData); 639 return new TestX509Certificate(subjName, issName); 640 } 641 642 /** 643 * Not supported yet. 644 * @throws UnsupportedOperationException 645 */ engineGenerateCertificates(InputStream inStream)646 public Collection engineGenerateCertificates(InputStream inStream) 647 throws CertificateException { 648 throw new UnsupportedOperationException("not yet."); 649 } 650 651 /** 652 * Not supported yet. 653 * @throws UnsupportedOperationException 654 */ engineGenerateCRL(InputStream inStream)655 public CRL engineGenerateCRL(InputStream inStream) throws CRLException { 656 throw new UnsupportedOperationException("not yet."); 657 } 658 659 /** 660 * Not supported yet. 661 * @throws UnsupportedOperationException 662 */ engineGenerateCRLs(InputStream inStream)663 public Collection engineGenerateCRLs(InputStream inStream) 664 throws CRLException { 665 throw new UnsupportedOperationException("not yet."); 666 } 667 668 /** 669 * Returns an instance of TestCertPath.<br> 670 * @throws CertificateException if 671 * a) any of Certificates passed is not an instance of X509Certificate 672 * b) any of Certificates passed is an instance of TestInvalidX509Certificate 673 */ engineGenerateCertPath(List certs)674 public CertPath engineGenerateCertPath(List certs) 675 throws CertificateException { 676 ArrayList validCerts = new ArrayList(); 677 for (Iterator i = certs.iterator(); i.hasNext();) { 678 Certificate c = (Certificate) i.next(); 679 if (!(c instanceof X509Certificate)) { 680 throw new CertificateException("Not X509: " + c); 681 } 682 if (c instanceof TestInvalidX509Certificate) { 683 throw new CertificateException("Invalid (test) X509: " + c); 684 } 685 validCerts.add(c); 686 } 687 Certificate[] acerts = new Certificate[validCerts.size()]; 688 validCerts.toArray(acerts); 689 return new TestCertPath(acerts); 690 } 691 } 692 693 /** 694 * Utility class used to generate some amount of uniq names. 695 */ 696 public static class UniGen { 697 public static final String rootName = "CN=Alex Astapchuk, OU=SSG, O=Intel ZAO, C=RU"; 698 699 private static final String datasNames[] = { "CN", "OU", "O", "C" }; 700 701 private static final String datas[][] = { 702 // Names database 703 { "Alex Astapchuk", null, null, null }, 704 { "John Doe", null, null, null }, 705 // 'organisation unit'-s 706 { null, "SSG", null, null }, { null, "SSG/DRL", null, null }, 707 // organizations 708 { null, null, "Intel ZAO", null }, 709 { null, null, "Intel Inc", null }, 710 // countries 711 { null, null, null, "RU" }, { null, null, null, "US" }, 712 { null, null, null, "GB" }, { null, null, null, "JA" }, 713 { null, null, null, "KO" }, { null, null, null, "TW" }, }; 714 715 // 716 // Returns a string from <code>data</code> from a given column and 717 // position. The positions are looked for first non-null entry. If there 718 // are no non empty items left, then it scans column starting from the 719 // beginning. 720 // 721 // @param col 722 // @param startRow 723 // @return 724 // getData(int col, int startRow)725 private static String getData(int col, int startRow) { 726 startRow = startRow % datas.length; 727 for (int i = startRow; i < datas.length; i++) { 728 if (datas[i][col] != null) { 729 return datas[i][col]; 730 } 731 } 732 // no non-null entries left, check from the beginning 733 for (int i = 0; i < datas.length; i++) { 734 if (datas[i][col] != null) { 735 return datas[i][col]; 736 } 737 } 738 // can't be 739 throw new Error(); 740 } 741 742 // 743 // Increments a num.<br> 744 // <code>num</code> is interpreted as a number with a base of 745 // <code>base</code> and each digit of this number is stored as a 746 // separate num's element. 747 // 748 // @param num 749 // @param base 750 // @return <b>true</b> if overflow happened 751 // inc(int[] num, int base)752 private static boolean inc(int[] num, int base) { 753 for (int i = 0; i < num.length; i++) { 754 if ((++num[i]) >= base) { 755 num[i] = 0; 756 } else { 757 return false; 758 } 759 } 760 return true; 761 } 762 763 /** 764 * Generates some amount of uniq names, none of which is equals to 765 * {@link #rootName}. 766 * @param howMany 767 * @return 768 */ genNames(int howMany)769 public static String[] genNames(int howMany) { 770 int counts[] = new int[datasNames.length]; 771 ArrayList al = new ArrayList(); 772 773 // not really the thrifty algorithm... 774 for (int i = 0; i < howMany;) { 775 776 // System.out.print("#"+i+": "); 777 // for( int j=0; j<counts.length; j++) { 778 // System.out.print(""+counts[j]+"|"); 779 // } 780 // System.out.println(); 781 782 StringBuffer buf = new StringBuffer(); 783 int j = 0; 784 for (; j < datasNames.length - 1; j++) { 785 String name = datasNames[j]; 786 String val = getData(j, counts[j]); 787 buf.append(name).append('=').append(val).append(","); 788 } 789 String name = datasNames[j]; 790 String val = getData(j, counts[j]); 791 buf.append(name).append('=').append(val); 792 793 name = buf.toString(); 794 795 if (!(rootName.equals(name) || al.contains(name))) { 796 ++i; 797 al.add(name); 798 // System.out.println("generated: "+name); 799 } else { 800 // System.out.println("rejected: "+name); 801 } 802 803 if (inc(counts, datas.length)) { 804 // if this happened, then just add some data into 'datas' 805 throw new Error( 806 "cant generate so many uniq names. sorry. add some more data."); 807 } 808 } 809 return (String[]) al.toArray(new String[al.size()]); 810 } 811 812 /** 813 * Generates some amount of uniq X500Principals, none of which is equals 814 * has a string equals to {@link #rootName}. 815 * @param howMany 816 * @return 817 */ genX500s(int howMany)818 public static X500Principal[] genX500s(int howMany) { 819 String names[] = genNames(howMany); 820 X500Principal[] ps = new X500Principal[howMany]; 821 for (int i = 0; i < howMany; i++) { 822 ps[i] = new X500Principal(names[i]); 823 } 824 return ps; 825 } 826 827 } 828 829 } 830 831