Package br.net.woodstock.rockframework.security.store.impl

Source Code of br.net.woodstock.rockframework.security.store.impl.XMLStore

/*
* This file is part of rockframework.
*
* rockframework is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* rockframework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>;.
*/
package br.net.woodstock.rockframework.security.store.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;

import javax.crypto.SecretKey;

import org.xml.sax.SAXException;

import br.net.woodstock.rockframework.core.RockFrameworkVersion;
import br.net.woodstock.rockframework.core.utils.Codecs;
import br.net.woodstock.rockframework.core.utils.Collections;
import br.net.woodstock.rockframework.core.utils.Conditions;
import br.net.woodstock.rockframework.core.xml.dom.XmlDocument;
import br.net.woodstock.rockframework.core.xml.dom.XmlElement;
import br.net.woodstock.rockframework.security.Identity;
import br.net.woodstock.rockframework.security.cert.util.Certificates;
import br.net.woodstock.rockframework.security.crypt.KeyPairType;
import br.net.woodstock.rockframework.security.crypt.KeyType;
import br.net.woodstock.rockframework.security.crypt.util.Keys;
import br.net.woodstock.rockframework.security.store.StoreException;

public class XMLStore extends MapStore {

  private static final long    serialVersionUID    = RockFrameworkVersion.VERSION;

  private static final Charset  CHARSET          = Charset.defaultCharset();

  private static final String    ENCODING        = XMLStore.CHARSET.name();

  private static final String    ALIAS_ATTRIBUTE      = "alias";

  private static final String    ALGORITHM_ATTRIBUTE    = "algorithm";

  private static final String    ENCODING_ATTRIBUTE    = "encoding";

  private static final String    STORE_ELEMENT      = "store";

  private static final String    CERTIFICATES_ELEMENT  = "certificates";

  private static final String    CHAIN_ELEMENT      = "chain";

  private static final String    PRIVATE_KEYS_ELEMENT  = "privateKeys";

  private static final String    PUBLIC_KEYS_ELEMENT    = "publicKeys";

  private static final String    SECRET_KEYS_ELEMENT    = "secretKeys";

  private static final String    CERTIFICATE_ELEMENT    = "certificate";

  private static final String    PRIVATE_KEY_ELEMENT    = "privateKey";

  private static final String    PUBLIC_KEY_ELEMENT    = "publicKey";

  private static final String    SECRET_KEY_ELEMENT    = "publicKey";

  public XMLStore() {
    super();
  }

  @Override
  public void read(final InputStream inputStream, final String password) throws IOException {
    try {
      XmlDocument document = XmlDocument.read(inputStream);
      XmlElement root = document.getRoot();

      String encoding = root.getAttribute(XMLStore.ENCODING_ATTRIBUTE);

      XmlElement certificates = root.getElement(XMLStore.CERTIFICATES_ELEMENT);
      XmlElement privateKeys = root.getElement(XMLStore.PRIVATE_KEYS_ELEMENT);
      XmlElement publicKeys = root.getElement(XMLStore.PUBLIC_KEYS_ELEMENT);
      XmlElement secretKeys = root.getElement(XMLStore.SECRET_KEYS_ELEMENT);

      for (XmlElement certificateElement : certificates.getElements()) {
        String alias = certificateElement.getAttribute(XMLStore.ALIAS_ATTRIBUTE);
        Certificate certificate = this.getCertificate(certificateElement, encoding);
        this.getCertificateMap().put(alias, certificate);
      }

      for (XmlElement privateKeyElement : privateKeys.getElements()) {
        String alias = privateKeyElement.getAttribute(XMLStore.ALIAS_ATTRIBUTE);
        Identity holder = this.getPrivateKey(privateKeyElement, encoding);
        this.getPrivateKeyMap().put(alias, holder);
      }

      for (XmlElement publicKeyElement : publicKeys.getElements()) {
        String alias = publicKeyElement.getAttribute(XMLStore.ALIAS_ATTRIBUTE);
        PublicKey publicKey = this.getPublicKey(publicKeyElement, encoding);
        this.getPublicKeyMap().put(alias, publicKey);
      }

      for (XmlElement secretKeyElement : secretKeys.getElements()) {
        String alias = secretKeyElement.getAttribute(XMLStore.ALIAS_ATTRIBUTE);
        SecretKey secretKey = this.getSecretKey(secretKeyElement, encoding);
        this.getSecretKeyMap().put(alias, secretKey);
      }
    } catch (GeneralSecurityException e) {
      throw new StoreException(e);
    } catch (SAXException e) {
      throw new StoreException(e);
    }
  }

  @Override
  public void write(final OutputStream outputStream, final String password) throws IOException {
    try {
      XmlDocument document = new XmlDocument(XMLStore.STORE_ELEMENT);

      XmlElement root = document.getRoot();
      root.setAttribute(XMLStore.ENCODING_ATTRIBUTE, XMLStore.ENCODING);

      XmlElement certificates = root.addElement(XMLStore.CERTIFICATES_ELEMENT);
      XmlElement privateKeys = root.addElement(XMLStore.PRIVATE_KEYS_ELEMENT);
      XmlElement publicKeys = root.addElement(XMLStore.PUBLIC_KEYS_ELEMENT);
      XmlElement secretKeys = root.addElement(XMLStore.SECRET_KEYS_ELEMENT);
      for (Entry<String, Certificate> entry : this.getCertificateMap().entrySet()) {
        String alias = entry.getKey();
        Certificate certificate = entry.getValue();
        this.addCertificateElement(certificates, alias, certificate);
      }
      for (Entry<String, Identity> entry : this.getPrivateKeyMap().entrySet()) {
        String alias = entry.getKey();
        Identity identity = entry.getValue();
        this.addPrivateKeyElement(privateKeys, alias, identity);
      }
      for (Entry<String, PublicKey> entry : this.getPublicKeyMap().entrySet()) {
        String alias = entry.getKey();
        PublicKey publicKey = entry.getValue();
        this.addPublicKeyElement(publicKeys, alias, publicKey);
      }
      for (Entry<String, SecretKey> entry : this.getSecretKeyMap().entrySet()) {
        String alias = entry.getKey();
        SecretKey secretKey = entry.getValue();
        this.addSecretKeyElement(secretKeys, alias, secretKey);
      }
      document.write(outputStream);
    } catch (GeneralSecurityException e) {
      throw new StoreException(e);
    }
  }

  private Certificate getCertificate(final XmlElement e, final String encoding) throws UnsupportedEncodingException {
    byte[] data = this.getBase64Data(e, encoding);

    Certificate certificate = Certificates.get(data);
    return certificate;
  }

  private Identity getPrivateKey(final XmlElement e, final String encoding) throws NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException {
    String algorithm = e.getAttribute(XMLStore.ALGORITHM_ATTRIBUTE);
    byte[] data = this.getBase64Data(e, encoding);

    PrivateKey privateKey = Keys.getPrivateKeyFromPKCS8File(data, KeyPairType.getKeyPairType(algorithm));

    List<Certificate> chainList = new ArrayList<Certificate>();
    Certificate[] chain = null;
    XmlElement chainElement = e.getElement(XMLStore.CHAIN_ELEMENT);
    for (XmlElement certificateElement : chainElement.getElements()) {
      Certificate certificate = this.getCertificate(certificateElement, encoding);
      chainList.add(certificate);
    }

    if (chainList.size() > 0) {
      chain = Collections.toArray(chainList, Certificate.class);
    }

    Identity identity = new Identity(privateKey, chain);
    return identity;
  }

  private PublicKey getPublicKey(final XmlElement e, final String encoding) throws NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException {
    String algorithm = e.getAttribute(XMLStore.ALGORITHM_ATTRIBUTE);
    byte[] data = this.getBase64Data(e, encoding);

    PublicKey publicKey = Keys.getPublicKeyFromX509File(data, KeyPairType.getKeyPairType(algorithm));
    return publicKey;
  }

  private SecretKey getSecretKey(final XmlElement e, final String encoding) throws UnsupportedEncodingException {
    String algorithm = e.getAttribute(XMLStore.ALGORITHM_ATTRIBUTE);
    byte[] data = this.getBase64Data(e, encoding);

    SecretKey secretKey = Keys.getSecretKeyFromFile(data, KeyType.getKeyType(algorithm));
    return secretKey;
  }

  private void addCertificateElement(final XmlElement parent, final String alias, final Certificate certificate) throws CertificateEncodingException, UnsupportedEncodingException {
    XmlElement certificateElement = parent.addElement(XMLStore.CERTIFICATE_ELEMENT);
    certificateElement.setAttribute(XMLStore.ALIAS_ATTRIBUTE, alias);
    certificateElement.setAttribute(XMLStore.ALGORITHM_ATTRIBUTE, certificate.getType());

    this.setBase64Data(certificateElement, certificate.getEncoded());
  }

  private void addPrivateKeyElement(final XmlElement parent, final String alias, final Identity identity) throws CertificateEncodingException, UnsupportedEncodingException {
    PrivateKey privateKey = identity.getPrivateKey();
    Certificate[] chain = identity.getChain();
    XmlElement privateKeyElement = parent.addElement(XMLStore.PRIVATE_KEY_ELEMENT);
    XmlElement chainElement = privateKeyElement.addElement(XMLStore.CHAIN_ELEMENT);
    privateKeyElement.setAttribute(XMLStore.ALIAS_ATTRIBUTE, alias);
    privateKeyElement.setAttribute(XMLStore.ALGORITHM_ATTRIBUTE, privateKey.getAlgorithm());

    this.setBase64Data(privateKeyElement, privateKey.getEncoded());

    if (Conditions.isNotEmpty(chain)) {
      for (Certificate certificate : chain) {
        this.addCertificateElement(chainElement, alias, certificate);
      }
    }
  }

  private void addPublicKeyElement(final XmlElement parent, final String alias, final PublicKey publicKey) throws UnsupportedEncodingException {
    XmlElement publicKeyElement = parent.addElement(XMLStore.PUBLIC_KEY_ELEMENT);
    publicKeyElement.setAttribute(XMLStore.ALIAS_ATTRIBUTE, alias);
    publicKeyElement.setAttribute(XMLStore.ALGORITHM_ATTRIBUTE, publicKey.getAlgorithm());

    this.setBase64Data(publicKeyElement, publicKey.getEncoded());
  }

  private void addSecretKeyElement(final XmlElement parent, final String alias, final SecretKey secretKey) throws UnsupportedEncodingException {
    XmlElement publicKeyElement = parent.addElement(XMLStore.SECRET_KEY_ELEMENT);
    publicKeyElement.setAttribute(XMLStore.ALIAS_ATTRIBUTE, alias);
    publicKeyElement.setAttribute(XMLStore.ALGORITHM_ATTRIBUTE, secretKey.getAlgorithm());

    this.setBase64Data(publicKeyElement, secretKey.getEncoded());
  }

  private byte[] getBase64Data(final XmlElement e, final String encoding) throws UnsupportedEncodingException {
    byte[] data64 = e.getData().getBytes(encoding);
    byte[] data = Codecs.fromBase64(data64);
    return data;
  }

  private void setBase64Data(final XmlElement e, final byte[] data) throws UnsupportedEncodingException {
    byte[] data64 = Codecs.toBase64(data);
    String str = new String(data64, XMLStore.ENCODING);
    e.setData(str);
  }
}
TOP

Related Classes of br.net.woodstock.rockframework.security.store.impl.XMLStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.