All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.named_data.jndn.security.identity.MemoryPrivateKeyStorage Maven / Gradle / Ivy

Go to download

jNDN is a new implementation of a Named Data Networking client library written in Java. It is wire format compatible with the new NDN-TLV encoding, with NDNx and PARC's CCNx.

There is a newer version: 0.25
Show newest version
/**
 * Copyright (C) 2013-2017 Regents of the University of California.
 * @author: Jeff Thompson 
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 * A copy of the GNU Lesser General Public License is in the file COPYING.
 */

package net.named_data.jndn.security.identity;

import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import net.named_data.jndn.Name;
import net.named_data.jndn.security.DigestAlgorithm;
import net.named_data.jndn.security.EcdsaKeyParams;
import net.named_data.jndn.security.KeyClass;
import net.named_data.jndn.security.KeyParams;
import net.named_data.jndn.security.KeyType;
import net.named_data.jndn.security.RsaKeyParams;
import net.named_data.jndn.security.SecurityException;
import net.named_data.jndn.security.certificate.PublicKey;
import net.named_data.jndn.util.Blob;

public class MemoryPrivateKeyStorage extends PrivateKeyStorage {
  /**
   * Set the public key for the keyName.
   * @param keyName The key name.
   * @param keyType The KeyType, such as KeyType.RSA.
   * @param publicKeyDer The public key DER byte buffer.
   * @throws SecurityException if can't decode the key DER.
   */
  public final void
  setPublicKeyForKeyName
    (Name keyName, KeyType keyType, ByteBuffer publicKeyDer) throws SecurityException
  {
    publicKeyStore_.put
      (keyName.toUri(), new PublicKey(new Blob(publicKeyDer, true)));
  }

  /**
   * Set the private key for the keyName.
   * @param keyName The key name.
   * @param keyType The KeyType, such as KeyType.RSA.
   * @param privateKeyDer The private key DER byte buffer.
   * @throws SecurityException if can't decode the key DER.
   */
  public final void
  setPrivateKeyForKeyName
    (Name keyName, KeyType keyType, ByteBuffer privateKeyDer) throws SecurityException
  {
    privateKeyStore_.put
      (keyName.toUri(), new PrivateKey(keyType, privateKeyDer));
  }

  /**
   * Set the public and private key for the keyName.
   * @param keyName The key name.
   * @param keyType The KeyType, such as KeyType.RSA.
   * @param publicKeyDer The public key DER byte buffer.
   * @param privateKeyDer The private key DER byte buffer.
   * @throws SecurityException if can't decode the key DER.
   */
  public final void
  setKeyPairForKeyName
    (Name keyName, KeyType keyType, ByteBuffer publicKeyDer,
     ByteBuffer privateKeyDer) throws SecurityException
  {
    setPublicKeyForKeyName(keyName, keyType, publicKeyDer);
    setPrivateKeyForKeyName(keyName, keyType, privateKeyDer);
  }

  /**
   * @deprecated Use setKeyPairForKeyName(keyName, KeyType.RSA, publicKeyDer, privateKeyDer).
   * @param keyName The key name.
   * @param publicKeyDer The public key DER byte buffer.
   * @param privateKeyDer The private key DER byte buffer.
   * @throws SecurityException if can't decode the key DER.
   */
  public final void
  setKeyPairForKeyName
    (Name keyName, ByteBuffer publicKeyDer, ByteBuffer privateKeyDer) throws SecurityException
  {
    setKeyPairForKeyName(keyName, KeyType.RSA, publicKeyDer, privateKeyDer);
  }

  /**
   * Generate a pair of asymmetric keys.
   * @param keyName The name of the key pair.
   * @param params The parameters of the key.
   * @throws SecurityException
   */
  public void
  generateKeyPair(Name keyName, KeyParams params) throws SecurityException
  {
    if (doesKeyExist(keyName, KeyClass.PUBLIC))
      throw new SecurityException("Public Key already exists");
    if (doesKeyExist(keyName, KeyClass.PRIVATE))
      throw new SecurityException("Private Key already exists");

    String keyAlgorithm;
    int keySize;
    if (params.getKeyType() == KeyType.RSA) {
      keyAlgorithm = "RSA";
      keySize = ((RsaKeyParams)params).getKeySize();
    }
    else if (params.getKeyType() == KeyType.ECDSA) {
      keyAlgorithm = "EC";
      keySize = ((EcdsaKeyParams)params).getKeySize();
    }
    else
      throw new SecurityException
        ("Cannot generate a key pair of type " + params.getKeyType());

    KeyPairGenerator generator = null;
    try{
      generator = KeyPairGenerator.getInstance(keyAlgorithm);
    }
    catch(NoSuchAlgorithmException e){
      throw new SecurityException
        ("FilePrivateKeyStorage: Could not create the key generator: " + e.getMessage());
    }

    generator.initialize(keySize);
    KeyPair pair = generator.generateKeyPair();

    setKeyPairForKeyName
      (keyName, params.getKeyType(), ByteBuffer.wrap(pair.getPublic().getEncoded()),
       ByteBuffer.wrap(pair.getPrivate().getEncoded()));
  }

  /**
   * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
   * @param keyName The name of the key pair.
   */
  public void
  deleteKeyPair(Name keyName) throws SecurityException
  {
    String keyUri = keyName.toUri();

    publicKeyStore_.remove(keyUri);
    privateKeyStore_.remove(keyUri);
  }

  /**
   * Get the public key
   * @param keyName The name of public key.
   * @return The public key.
   * @throws SecurityException
   */
  public PublicKey
  getPublicKey(Name keyName) throws SecurityException
  {
    PublicKey publicKey = (PublicKey)publicKeyStore_.get(keyName.toUri());
    if (publicKey == null)
      throw new SecurityException
        ("MemoryPrivateKeyStorage: Cannot find public key " + keyName.toUri());
    return publicKey;
  }

  /**
   * Fetch the private key for keyName and sign the data, returning a signature
   * Blob.
   * @param data Pointer the input byte buffer to sign.
   * @param keyName The name of the signing key.
   * @param digestAlgorithm the digest algorithm.
   * @return The signature Blob.
   * @throws SecurityException
   */
  public Blob
  sign(ByteBuffer data, Name keyName, DigestAlgorithm digestAlgorithm)
       throws SecurityException
  {
    if (digestAlgorithm != DigestAlgorithm.SHA256)
      throw new SecurityException
        ("MemoryPrivateKeyStorage.sign: Unsupported digest algorithm");

    // Find the private key and sign.
    PrivateKey privateKey = (PrivateKey)privateKeyStore_.get(keyName.toUri());
    if (privateKey == null)
      throw new SecurityException
        ("MemoryPrivateKeyStorage: Cannot find private key " + keyName.toUri());

    java.security.Signature signature = null;
    if (privateKey.getKeyType() == KeyType.RSA) {
      try {
        signature = java.security.Signature.getInstance("SHA256withRSA");
      }
      catch (NoSuchAlgorithmException e) {
        // Don't expect this to happen.
        throw new SecurityException("SHA256withRSA algorithm is not supported");
      }
    }
    else if (privateKey.getKeyType() == KeyType.ECDSA) {
      try {
        signature = java.security.Signature.getInstance("SHA256withECDSA");
      }
      catch (NoSuchAlgorithmException e) {
        // Don't expect this to happen.
        throw new SecurityException("SHA256withECDSA algorithm is not supported");
      }
    }
    else
      // We don't expect this to happen.
      throw new SecurityException("Unrecognized private key type");

    try {
      signature.initSign(privateKey.getPrivateKey());
    }
    catch (InvalidKeyException exception) {
      throw new SecurityException
        ("InvalidKeyException: " + exception.getMessage());
    }
    try {
      signature.update(data);
      return new Blob(signature.sign(), false);
    }
    catch (SignatureException exception) {
      throw new SecurityException
        ("SignatureException: " + exception.getMessage());
    }
  }

  /**
   * Decrypt data.
   * @param keyName The name of the decrypting key.
   * @param data The byte buffer to be decrypted, from its position to its
   * limit.
   * @param isSymmetric If true symmetric encryption is used, otherwise
   * asymmetric encryption is used.
   * @return The decrypted data.
   * @throws SecurityException
   */
  public Blob
  decrypt(Name keyName, ByteBuffer data, boolean isSymmetric)
          throws SecurityException
  {
    throw new UnsupportedOperationException
      ("MemoryPrivateKeyStorage.decrypt is not implemented");
  }

  /**
   * Encrypt data.
   * @param keyName The name of the encrypting key.
   * @param data The byte buffer to be encrypted, from its position to its
   * limit.
   * @param isSymmetric If true symmetric encryption is used, otherwise
   * asymmetric encryption is used.
   * @return The encrypted data.
   * @throws SecurityException
   */
  public Blob
  encrypt(Name keyName, ByteBuffer data, boolean isSymmetric)
         throws SecurityException
  {
    throw new UnsupportedOperationException
      ("MemoryPrivateKeyStorage.encrypt is not implemented");
  }

  /**
   * Generate a symmetric key.
   * @param keyName The name of the key.
   * @param params The parameters of the key.
   * @throws SecurityException
   */
  public void
  generateKey(Name keyName, KeyParams params) throws SecurityException
  {
    throw new UnsupportedOperationException
      ("MemoryPrivateKeyStorage.generateKey is not implemented");
  }

  /**
   * Check if a particular key exists.
   * @param keyName The name of the key.
   * @param keyClass The class of the key, e.g. KEY_CLASS_PUBLIC,
   * KEY_CLASS_PRIVATE, or KEY_CLASS_SYMMETRIC.
   * @return True if the key exists, otherwise false.
   */
  public boolean
  doesKeyExist(Name keyName, KeyClass keyClass) throws SecurityException
  {
    if (keyClass == KeyClass.PUBLIC)
      return publicKeyStore_.containsKey(keyName.toUri());
    else if (keyClass == KeyClass.PRIVATE)
      return privateKeyStore_.containsKey(keyName.toUri());
    else
      // KeyClass.SYMMETRIC not implemented yet.
      return false;
  }

  /**
   * PrivateKey is a simple class to hold a java.security.PrivateKey along with
   * a KeyType.
   */
  class PrivateKey {
    public PrivateKey(KeyType keyType, ByteBuffer keyDer) throws SecurityException {
      keyType_ = keyType;

      if (keyType == KeyType.RSA) {
        KeyFactory keyFactory = null;
        try {
          keyFactory = KeyFactory.getInstance("RSA");
        }
        catch (NoSuchAlgorithmException exception) {
          // Don't expect this to happen.
          throw new SecurityException
            ("KeyFactory: RSA is not supported: " + exception.getMessage());
        }

        try {
          privateKey_ =
            keyFactory.generatePrivate
              (new PKCS8EncodedKeySpec(new Blob(keyDer, false).getImmutableArray()));
        }
        catch (InvalidKeySpecException exception) {
          // Don't expect this to happen.
          throw new SecurityException
            ("KeyFactory: PKCS8EncodedKeySpec is not supported for RSA: " +
             exception.getMessage());
        }
      }
      else if (keyType == KeyType.ECDSA) {
        KeyFactory keyFactory = null;
        try {
          keyFactory = KeyFactory.getInstance("EC");
        }
        catch (NoSuchAlgorithmException exception) {
          // Don't expect this to happen.
          throw new SecurityException
            ("KeyFactory: EC is not supported: " + exception.getMessage());
        }

        try {
          privateKey_ =
            keyFactory.generatePrivate
              (new PKCS8EncodedKeySpec(new Blob(keyDer, false).getImmutableArray()));
        }
        catch (InvalidKeySpecException exception) {
          // Don't expect this to happen.
          throw new SecurityException
            ("KeyFactory: PKCS8EncodedKeySpec is not supported for EC: " +
             exception.getMessage());
        }
      }
      else
        throw new SecurityException
          ("PrivateKey constructor: Unrecognized keyType");
    }

    public KeyType getKeyType() { return keyType_; }

    public java.security.PrivateKey getPrivateKey() { return privateKey_; }

    private KeyType keyType_;
    private java.security.PrivateKey privateKey_;
  }

  // Use HashMap without generics so it works with older Java compilers.
  private final HashMap publicKeyStore_ =
    new HashMap(); /**< The map key is the keyName.toUri().
                      * The value is security.certificate.PublicKey. */
  private final HashMap privateKeyStore_ =
    new HashMap(); /**< The map key is the keyName.toUri().
                      * The value is MemoryPrivateKeyStorage.PrivateKey. */
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy