/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.usergrid.rest.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.SimpleTimeZone;
public class CertificateUtils {
private static final Logger logger = LoggerFactory.getLogger(CertificateUtils.class);
private static final String APPLE_TOPIC_OID = "1.2.840.113635.100.6.3.6";
public static Map<String, Object> getCertAtrributes(byte[] certBytes, String certPassword){
if(certPassword == null){
certPassword = ""; // if there is no password, pass in empty string
}
SimpleDateFormat dateFormat = new SimpleDateFormat();
dateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
dateFormat.applyPattern("EEE dd MMM yyyy HH:mm:ss z"); // GMT String format
Map<String,Object> attributes = new HashMap<>(1);
try{
KeyStore p12 = KeyStore.getInstance("pkcs12");
InputStream stream = new ByteArrayInputStream(certBytes);
p12.load(stream, certPassword.toCharArray());
Enumeration aliases = p12.aliases();
while(aliases.hasMoreElements()){
String alias = (String) aliases.nextElement();
X509Certificate cert = (X509Certificate) p12.getCertificate(alias);
attributes.put("subject", cert.getSubjectDN().toString());
attributes.put("validFrom", dateFormat.format(cert.getNotBefore()));
attributes.put("validFromTimestamp", cert.getNotBefore().getTime());
attributes.put("validTo", dateFormat.format(cert.getNotAfter()));
attributes.put("validToTimestamp", cert.getNotAfter().getTime());
attributes.put("issuer", cert.getIssuerDN().toString());
attributes.put("subjectAlternativeNames", cert.getSubjectAlternativeNames());
// Apple uses a specific extension OID for their universal cert structure and push topics
Map<String,Object> extensions = new HashMap<>(1);
if(cert.getExtensionValue(APPLE_TOPIC_OID) != null){
extensions.put(APPLE_TOPIC_OID, cert.getExtensionValue(APPLE_TOPIC_OID));
}
attributes.put("extensions", extensions);
attributes.put("extendedKeyUsages", cert.getExtendedKeyUsage());
attributes.put("version", cert.getVersion());
attributes.put("signatureAlgorithm", cert.getSigAlgName());
attributes.put("serialNumber", cert.getSerialNumber());
attributes.put("basicConstraints", cert.getBasicConstraints());
}
}catch (Exception e){
String message = "Unable load certificate details. Possible invalid p12 file.";
throw new RuntimeException(message, e);
}
return attributes;
}
public static boolean isValid(Map<String, Object> certAttributes) {
if(certAttributes == null || certAttributes.isEmpty()){
return false;
}
// check to make sure the certificate is not expired
final long currentTime = System.currentTimeMillis();
final long validToTimestamp = (long) certAttributes.get("validToTimestamp");
// if the current time doesn't fall into the certs
if(currentTime > validToTimestamp){
logger.error("Certificate is not valid due to time. Cert Valid To: {}", validToTimestamp);
return false;
}
return true;
}
}