예제 #1
0
  /**
   * Returns the encoded SPNEGO token Note: inserts the required CHOICE tags
   *
   * @return the encoded token
   * @exception GSSException
   */
  byte[] getEncoded() throws IOException, GSSException {

    // get the token encoded value
    DerOutputStream token = new DerOutputStream();
    token.write(encode());

    // now insert the CHOICE
    switch (tokenType) {
      case NEG_TOKEN_INIT_ID:
        // Insert CHOICE of Negotiation Token
        DerOutputStream initToken = new DerOutputStream();
        initToken.write(
            DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) NEG_TOKEN_INIT_ID), token);
        return initToken.toByteArray();

      case NEG_TOKEN_TARG_ID:
        // Insert CHOICE of Negotiation Token
        DerOutputStream targToken = new DerOutputStream();
        targToken.write(
            DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) NEG_TOKEN_TARG_ID), token);
        return targToken.toByteArray();
      default:
        return token.toByteArray();
    }
  }
예제 #2
0
  @SuppressWarnings("deprecation")
  private byte[] extractKeyData(DerInputStream stream)
      throws IOException, NoSuchAlgorithmException, CertificateException {
    byte[] returnValue = null;
    DerValue[] safeBags = stream.getSequence(2);
    int count = safeBags.length;

    /*
     * Spin over the SafeBags.
     */
    for (int i = 0; i < count; i++) {
      ObjectIdentifier bagId;
      DerInputStream sbi;
      DerValue bagValue;
      Object bagItem = null;

      sbi = safeBags[i].toDerInputStream();
      bagId = sbi.getOID();
      bagValue = sbi.getDerValue();
      if (!bagValue.isContextSpecific((byte) 0)) {
        throw new IOException("unsupported PKCS12 bag value type " + bagValue.tag);
      }
      bagValue = bagValue.data.getDerValue();
      if (bagId.equals(PKCS8ShroudedKeyBag_OID)) {
        // got what we were looking for.  Return it.
        returnValue = bagValue.toByteArray();
      } else {
        // log error message for "unsupported PKCS12 bag type"
        System.out.println("Unsupported bag type '" + bagId + "'");
      }
    }

    return returnValue;
  }
 /**
  * Check if the certificate allows use of the given DNS name.
  *
  * <p>From RFC2818: If a subjectAltName extension of type dNSName is present, that MUST be used as
  * the identity. Otherwise, the (most specific) Common Name field in the Subject field of the
  * certificate MUST be used. Although the use of the Common Name is existing practice, it is
  * deprecated and Certification Authorities are encouraged to use the dNSName instead.
  *
  * <p>Matching is performed using the matching rules specified by [RFC2459]. If more than one
  * identity of a given type is present in the certificate (e.g., more than one dNSName name, a
  * match in any one of the set is considered acceptable.)
  */
 private void matchDNS(String expectedName, X509Certificate cert) throws CertificateException {
   Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
   if (subjAltNames != null) {
     boolean foundDNS = false;
     for (List<?> next : subjAltNames) {
       if (((Integer) next.get(0)).intValue() == ALTNAME_DNS) {
         foundDNS = true;
         String dnsName = (String) next.get(1);
         if (isMatched(expectedName, dnsName)) {
           return;
         }
       }
     }
     if (foundDNS) {
       // if certificate contains any subject alt names of type DNS
       // but none match, reject
       throw new CertificateException(
           "No subject alternative DNS " + "name matching " + expectedName + " found.");
     }
   }
   X500Name subjectName = getSubjectX500Name(cert);
   DerValue derValue = subjectName.findMostSpecificAttribute(X500Name.commonName_oid);
   if (derValue != null) {
     try {
       if (isMatched(expectedName, derValue.getAsString())) {
         return;
       }
     } catch (IOException e) {
       // ignore
     }
   }
   String msg = "No name matching " + expectedName + " found";
   throw new CertificateException(msg);
 }
예제 #4
0
  @SuppressWarnings("deprecation")
  private byte[] fetchPrivateKeyFromBag(byte[] privateKeyInfo)
      throws IOException, NoSuchAlgorithmException, CertificateException {
    byte[] returnValue = null;
    DerValue val = new DerValue(new ByteArrayInputStream(privateKeyInfo));
    DerInputStream s = val.toDerInputStream();
    int version = s.getInteger();

    if (version != 3) {
      throw new IOException("PKCS12 keystore not in version 3 format");
    }

    /*
     * Read the authSafe.
     */
    byte[] authSafeData;
    ContentInfo authSafe = new ContentInfo(s);
    ObjectIdentifier contentType = authSafe.getContentType();

    if (contentType.equals(ContentInfo.DATA_OID)) {
      authSafeData = authSafe.getData();
    } else /* signed data */ {
      throw new IOException("public key protected PKCS12 not supported");
    }

    DerInputStream as = new DerInputStream(authSafeData);
    DerValue[] safeContentsArray = as.getSequence(2);
    int count = safeContentsArray.length;

    /*
     * Spin over the ContentInfos.
     */
    for (int i = 0; i < count; i++) {
      byte[] safeContentsData;
      ContentInfo safeContents;
      DerInputStream sci;
      byte[] eAlgId = null;

      sci = new DerInputStream(safeContentsArray[i].toByteArray());
      safeContents = new ContentInfo(sci);
      contentType = safeContents.getContentType();
      safeContentsData = null;

      if (contentType.equals(ContentInfo.DATA_OID)) {
        safeContentsData = safeContents.getData();
      } else if (contentType.equals(ContentInfo.ENCRYPTED_DATA_OID)) {
        // The password was used to export the private key from the keychain.
        // The Keychain won't export the key with encrypted data, so we don't need
        // to worry about it.
        continue;
      } else {
        throw new IOException("public key protected PKCS12" + " not supported");
      }
      DerInputStream sc = new DerInputStream(safeContentsData);
      returnValue = extractKeyData(sc);
    }

    return returnValue;
  }
예제 #5
0
 /**
  * Parse (unmarshal) a realm from a DER input stream. This form parsing might be used when
  * expanding a value which is part of a constructed sequence and uses explicitly tagged type.
  *
  * @exception Asn1Exception on error.
  * @param data the Der input stream value, which contains one or more marshaled value.
  * @param explicitTag tag number.
  * @param optional indicate if this data field is optional
  * @return an instance of Realm.
  */
 public static Realm parse(DerInputStream data, byte explicitTag, boolean optional)
     throws Asn1Exception, IOException, RealmException {
   if ((optional) && (((byte) data.peekByte() & (byte) 0x1F) != explicitTag)) {
     return null;
   }
   DerValue der = data.getDerValue();
   if (explicitTag != (der.getTag() & (byte) 0x1F)) {
     throw new Asn1Exception(Krb5.ASN1_BAD_ID);
   } else {
     DerValue subDer = der.getData().getDerValue();
     return new Realm(subDer);
   }
 }
예제 #6
0
 /*
  * parse Algorithm Parameters
  */
 private AlgorithmParameters parseAlgParameters(DerInputStream in) throws IOException {
   AlgorithmParameters algParams = null;
   try {
     DerValue params;
     if (in.available() == 0) {
       params = null;
     } else {
       params = in.getDerValue();
       if (params.tag == DerValue.tag_Null) {
         params = null;
       }
     }
     if (params != null) {
       algParams = AlgorithmParameters.getInstance("PBE");
       algParams.init(params.toByteArray());
     }
   } catch (Exception e) {
     IOException ioe = new IOException("parseAlgParameters failed: " + e.getMessage());
     ioe.initCause(e);
     throw ioe;
   }
   return algParams;
 }
예제 #7
0
  /**
   * Returns the key associated with the given alias, using the given password to recover it.
   *
   * @param alias the alias name
   * @param password the password for recovering the key. This password is used internally as the
   *     key is exported in a PKCS12 format.
   * @return the requested key, or null if the given alias does not exist or does not identify a
   *     <i>key entry</i>.
   * @exception NoSuchAlgorithmException if the algorithm for recovering the key cannot be found
   * @exception UnrecoverableKeyException if the key cannot be recovered (e.g., the given password
   *     is wrong).
   */
  public Key engineGetKey(String alias, char[] password)
      throws NoSuchAlgorithmException, UnrecoverableKeyException {
    permissionCheck();

    // An empty password is rejected by MacOS API, no private key data
    // is exported. If no password is passed (as is the case when
    // this implementation is used as browser keystore in various
    // deployment scenarios like Webstart, JFX and applets), create
    // a dummy password so MacOS API is happy.
    if (password == null || password.length == 0) {
      // Must not be a char array with only a 0, as this is an empty
      // string.
      if (random == null) {
        random = new SecureRandom();
      }
      password = Long.toString(random.nextLong()).toCharArray();
    }

    Object entry = entries.get(alias.toLowerCase());

    if (entry == null || !(entry instanceof KeyEntry)) {
      return null;
    }

    // This call gives us a PKCS12 bag, with the key inside it.
    byte[] exportedKeyInfo = _getEncodedKeyData(((KeyEntry) entry).keyRef, password);
    if (exportedKeyInfo == null) {
      return null;
    }

    PrivateKey returnValue = null;

    try {
      byte[] pkcs8KeyData = fetchPrivateKeyFromBag(exportedKeyInfo);
      byte[] encryptedKey;
      AlgorithmParameters algParams;
      ObjectIdentifier algOid;
      try {
        // get the encrypted private key
        EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(pkcs8KeyData);
        encryptedKey = encrInfo.getEncryptedData();

        // parse Algorithm parameters
        DerValue val = new DerValue(encrInfo.getAlgorithm().encode());
        DerInputStream in = val.toDerInputStream();
        algOid = in.getOID();
        algParams = parseAlgParameters(in);

      } catch (IOException ioe) {
        UnrecoverableKeyException uke =
            new UnrecoverableKeyException(
                "Private key not stored as " + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
        uke.initCause(ioe);
        throw uke;
      }

      // Use JCE to decrypt the data using the supplied password.
      SecretKey skey = getPBEKey(password);
      Cipher cipher = Cipher.getInstance(algOid.toString());
      cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
      byte[] decryptedPrivateKey = cipher.doFinal(encryptedKey);
      PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(decryptedPrivateKey);

      // Parse the key algorithm and then use a JCA key factory to create the private key.
      DerValue val = new DerValue(decryptedPrivateKey);
      DerInputStream in = val.toDerInputStream();

      // Ignore this -- version should be 0.
      int i = in.getInteger();

      // Get the Algorithm ID next
      DerValue[] value = in.getSequence(2);
      AlgorithmId algId = new AlgorithmId(value[0].getOID());
      String algName = algId.getName();

      // Get a key factory for this algorithm.  It's likely to be 'RSA'.
      KeyFactory kfac = KeyFactory.getInstance(algName);
      returnValue = kfac.generatePrivate(kspec);
    } catch (Exception e) {
      UnrecoverableKeyException uke =
          new UnrecoverableKeyException("Get Key failed: " + e.getMessage());
      uke.initCause(e);
      throw uke;
    }

    return returnValue;
  }