示例#1
0
    /**
     * Add an attribute to the section
     *
     * @param attribute the attribute to be added.
     * @return the value of the attribute if it is a name attribute - null other wise
     * @throws ManifestException if the attribute already exists in this section.
     */
    public String addAttributeAndCheck(Attribute attribute) throws ManifestException {
      if (attribute.getName() == null || attribute.getValue() == null) {
        throw new ManifestException("Attributes must have name and value");
      }
      if (attribute.getKey().equalsIgnoreCase(ATTRIBUTE_NAME)) {
        warnings.addElement(
            "\""
                + ATTRIBUTE_NAME
                + "\" attributes "
                + "should not occur in the main section and must be the "
                + "first element in all other sections: \""
                + attribute.getName()
                + ": "
                + attribute.getValue()
                + "\"");
        return attribute.getValue();
      }

      if (attribute.getKey().startsWith(ATTRIBUTE_FROM.toLowerCase())) {
        warnings.addElement(
            "Manifest attributes should not start "
                + "with \""
                + ATTRIBUTE_FROM
                + "\" in \""
                + attribute.getName()
                + ": "
                + attribute.getValue()
                + "\"");
      } else {
        // classpath attributes go into a vector
        String attributeKey = attribute.getKey();
        if (attributeKey.equalsIgnoreCase(ATTRIBUTE_CLASSPATH)) {
          Attribute classpathAttribute = (Attribute) attributes.get(attributeKey);

          if (classpathAttribute == null) {
            storeAttribute(attribute);
          } else {
            warnings.addElement(
                "Multiple Class-Path attributes "
                    + "are supported but violate the Jar "
                    + "specification and may not be correctly "
                    + "processed in all environments");
            Enumeration e = attribute.getValues();
            while (e.hasMoreElements()) {
              String value = (String) e.nextElement();
              classpathAttribute.addValue(value);
            }
          }
        } else if (attributes.containsKey(attributeKey)) {
          throw new ManifestException(
              "The attribute \""
                  + attribute.getName()
                  + "\" may not occur more "
                  + "than once in the same section");
        } else {
          storeAttribute(attribute);
        }
      }
      return null;
    }
示例#2
0
    /**
     * Merge in another section
     *
     * @param section the section to be merged with this one.
     * @throws ManifestException if the sections cannot be merged.
     */
    public void merge(Section section) throws ManifestException {
      if (name == null && section.getName() != null
          || name != null && !(name.equalsIgnoreCase(section.getName()))) {
        throw new ManifestException("Unable to merge sections with different names");
      }

      Enumeration e = section.getAttributeKeys();
      Attribute classpathAttribute = null;
      while (e.hasMoreElements()) {
        String attributeName = (String) e.nextElement();
        Attribute attribute = section.getAttribute(attributeName);
        if (attributeName.equalsIgnoreCase(ATTRIBUTE_CLASSPATH)) {
          if (classpathAttribute == null) {
            classpathAttribute = new Attribute();
            classpathAttribute.setName(ATTRIBUTE_CLASSPATH);
          }
          Enumeration cpe = attribute.getValues();
          while (cpe.hasMoreElements()) {
            String value = (String) cpe.nextElement();
            classpathAttribute.addValue(value);
          }
        } else {
          // the merge file always wins
          storeAttribute(attribute);
        }
      }

      if (classpathAttribute != null) {
        // the merge file *always* wins, even for Class-Path
        storeAttribute(classpathAttribute);
      }

      // add in the warnings
      Enumeration warnEnum = section.warnings.elements();
      while (warnEnum.hasMoreElements()) {
        warnings.addElement(warnEnum.nextElement());
      }
    }
示例#3
0
  public static void main(String[] args) {

    try {

      // Read arguments
      if (args.length != 3) {
        System.out.println("Usage: PFX <dbdir> <infile> <outfile>");
        System.exit(-1);
      }

      // open input file for reading
      FileInputStream infile = null;
      try {
        infile = new FileInputStream(args[1]);
      } catch (FileNotFoundException f) {
        System.out.println("Cannot open file " + args[1] + " for reading: " + f.getMessage());
        return;
      }
      int certfile = 0;

      // initialize CryptoManager. This is necessary because there is
      // crypto involved with decoding a PKCS #12 file
      CryptoManager.initialize(args[0]);
      CryptoManager manager = CryptoManager.getInstance();

      // Decode the P12 file
      PFX.Template pfxt = new PFX.Template();
      PFX pfx = (PFX) pfxt.decode(new BufferedInputStream(infile, 2048));
      System.out.println("Decoded PFX");

      // print out information about the top-level PFX structure
      System.out.println("Version: " + pfx.getVersion());
      AuthenticatedSafes authSafes = pfx.getAuthSafes();
      SEQUENCE safeContentsSequence = authSafes.getSequence();
      System.out.println("AuthSafes has " + safeContentsSequence.size() + " SafeContents");

      // Get the password for the old file
      System.out.println("Enter password: "******"Enter new password:"******"AuthSafes verifies correctly.");
      } else {
        System.out.println("AuthSafes failed to verify because: " + sb);
      }

      // Create a new AuthenticatedSafes. As we read the contents of the
      // old authSafes, we will store them into the new one.  After we have
      // cycled through all the contents, they will all have been copied into
      // the new authSafes.
      AuthenticatedSafes newAuthSafes = new AuthenticatedSafes();

      // Loop over contents of the old authenticated safes
      // for(int i=0; i < asSeq.size(); i++) {
      for (int i = 0; i < safeContentsSequence.size(); i++) {

        // The safeContents may or may not be encrypted.  We always send
        // the password in.  It will get used if it is needed.  If the
        // decryption of the safeContents fails for some reason (like
        // a bad password), then this method will throw an exception
        SEQUENCE safeContents = authSafes.getSafeContentsAt(pass, i);

        System.out.println("\n\nSafeContents #" + i + " has " + safeContents.size() + " bags");

        // Go through all the bags in this SafeContents
        for (int j = 0; j < safeContents.size(); j++) {
          SafeBag safeBag = (SafeBag) safeContents.elementAt(j);

          // The type of the bag is an OID
          System.out.println("\nBag " + j + " has type " + safeBag.getBagType());

          // look for bag attributes
          SET attribs = safeBag.getBagAttributes();
          if (attribs == null) {
            System.out.println("Bag has no attributes");
          } else {
            for (int b = 0; b < attribs.size(); b++) {
              Attribute a = (Attribute) attribs.elementAt(b);
              if (a.getType().equals(SafeBag.FRIENDLY_NAME)) {
                // the friendly name attribute is a nickname
                BMPString bs =
                    (BMPString)
                        ((ANY) a.getValues().elementAt(0)).decodeWith(BMPString.getTemplate());
                System.out.println("Friendly Name: " + bs);
              } else if (a.getType().equals(SafeBag.LOCAL_KEY_ID)) {
                // the local key id is used to match a key
                // to its cert.  The key id is the SHA-1 hash of
                // the DER-encoded cert.
                OCTET_STRING os =
                    (OCTET_STRING)
                        ((ANY) a.getValues().elementAt(0)).decodeWith(OCTET_STRING.getTemplate());
                System.out.println("LocalKeyID:");
                /*
                                     AuthenticatedSafes.
                                         print_byte_array(os.toByteArray());
                */
              } else {
                System.out.println("Unknown attribute type: " + a.getType().toString());
              }
            }
          }

          // now look at the contents of the bag
          ASN1Value val = safeBag.getInterpretedBagContent();

          if (val instanceof PrivateKeyInfo) {
            // A PrivateKeyInfo contains an unencrypted private key
            System.out.println("content is PrivateKeyInfo");
          } else if (val instanceof EncryptedPrivateKeyInfo) {
            // An EncryptedPrivateKeyInfo is, well, an encrypted
            // PrivateKeyInfo. Usually, strong crypto is used in
            // an EncryptedPrivateKeyInfo.
            EncryptedPrivateKeyInfo epki = ((EncryptedPrivateKeyInfo) val);
            System.out.println(
                "content is EncryptedPrivateKeyInfo, algoid:"
                    + epki.getEncryptionAlgorithm().getOID());

            // Because we are in a PKCS #12 file, the passwords are
            // char-to-byte converted in a special way.  We have to
            // use the special converter class instead of the default.
            PrivateKeyInfo pki = epki.decrypt(pass, new org.mozilla.jss.pkcs12.PasswordConverter());

            // import the key into the key3.db
            CryptoToken tok = manager.getTokenByName("Internal Key Storage Token");
            CryptoStore store = tok.getCryptoStore();
            tok.login(new ConsolePasswordCallback());
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            pki.encode(baos);
            store.importPrivateKey(baos.toByteArray(), PrivateKey.RSA);

            // re-encrypt the PrivateKeyInfo with the new password
            // and random salt
            byte[] salt = new byte[PBEAlgorithm.PBE_SHA1_DES3_CBC.getSaltLength()];
            JSSSecureRandom rand = CryptoManager.getInstance().getSecureRNG();
            rand.nextBytes(salt);
            epki =
                EncryptedPrivateKeyInfo.createPBE(
                    PBEAlgorithm.PBE_SHA1_DES3_CBC, newPass, salt, 1, new PasswordConverter(), pki);

            // Overwrite the previous EncryptedPrivateKeyInfo with
            // this new one we just created using the new password.
            // This is what will get put in the new PKCS #12 file
            // we are creating.
            safeContents.insertElementAt(
                new SafeBag(safeBag.getBagType(), epki, safeBag.getBagAttributes()), i);
            safeContents.removeElementAt(i + 1);

          } else if (val instanceof CertBag) {
            System.out.println("content is CertBag");
            CertBag cb = (CertBag) val;
            if (cb.getCertType().equals(CertBag.X509_CERT_TYPE)) {
              // this is an X.509 certificate
              OCTET_STRING os = (OCTET_STRING) cb.getInterpretedCert();
              Certificate cert =
                  (Certificate) ASN1Util.decode(Certificate.getTemplate(), os.toByteArray());
              cert.getInfo().print(System.out);
            } else {
              System.out.println("Unrecognized cert type");
            }
          } else {
            System.out.println("content is ANY");
          }
        }

        // Add the new safe contents to the new authsafes
        if (authSafes.safeContentsIsEncrypted(i)) {
          newAuthSafes.addEncryptedSafeContents(
              authSafes.DEFAULT_KEY_GEN_ALG,
              newPass,
              null,
              authSafes.DEFAULT_ITERATIONS,
              safeContents);
        } else {
          newAuthSafes.addSafeContents(safeContents);
        }
      }

      // Create new PFX from the new authsafes
      PFX newPfx = new PFX(newAuthSafes);

      // Add a MAC to the new PFX
      newPfx.computeMacData(newPass, null, PFX.DEFAULT_ITERATIONS);

      // write the new PFX out to a file
      FileOutputStream fos = new FileOutputStream(args[2]);
      newPfx.encode(fos);
      fos.close();

    } catch (Exception e) {
      e.printStackTrace();
    }
  }