Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (C) 2014-2015 Regents of the University of California.

Author(s):
Jeff Thompson <jefft0@remap.ucla.edu> 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 <http://www.gnu.org/licenses/>. A copy of the GNU Lesser General Public License is in the file COPYING.
 
 
 package net.named_data.jndn.security.identity;
 
 import java.io.File;
 import java.util.List;
FilePrivateKeyStorage extends PrivateKeyStorage to implement private key storage using files.
 
 public class FilePrivateKeyStorage extends PrivateKeyStorage {
  
Create a new FilePrivateKeyStorage to connect to the default directory in System.getProperty("user.home").
 
   public FilePrivateKeyStorage()
   {
      = new File
       (getDefaultDirecoryPath(System.getProperty("user.home"".")));
     .mkdirs();
   }

  
Create a new FilePrivateKeyStorage to connect to the given directory.

Parameters:
keyStoreDirectoryPath The full path of the directory holding the private key data. This creates the directory if it doesn't exist. For example, you can get the default directory path from an Android files directory with getDefaultDirecoryPath(context.getFilesDir())
 
   public FilePrivateKeyStorage(String keyStoreDirectoryPath)
   {
      = new File(keyStoreDirectoryPath);
     .mkdirs();
   }

  
Get the default directory path for private keys based on the files root. For example if filesRoot is "/data/data/org.example/files", this returns "/data/data/org.example/files/.ndn/ndnsec-tpm-file".

Parameters:
filesRoot The root file directory. An Android app can use context.getFilesDir()
Returns:
The default directory path.
 
   public static String
   getDefaultDirecoryPath(File filesRoot)
   {
     return getDefaultDirecoryPath(filesRoot.getAbsolutePath());
   }

  
Get the default directory path for private keys based on the files root.

Parameters:
filesRoot The root file directory.
Returns:
The default directory path.
  public static String
  {
    // NOTE: Use File because java.nio.file.Path is not available before Java 7.
    return new File(new File(filesRoot".ndn"), "ndnsec-tpm-file").getAbsolutePath();
  }

  
Generate a pair of asymmetric keys.

Parameters:
keyName The name of the key pair.
params The parameters of the key.
Throws:
net.named_data.jndn.security.SecurityException
  public final void
  generateKeyPair(Name keyNameKeyParams paramsthrows SecurityException
  {
    if (doesKeyExist(keyName.))
      throw new SecurityException("Public Key already exists");
    if (doesKeyExist(keyName.))
      throw new SecurityException("Private Key already exists");
    String keyAlgorithm;
    int keySize;
    if (params.getKeyType() == .) {
      keyAlgorithm = "RSA";
      keySize = ((RsaKeyParams)params).getKeySize();
    }
    else if (params.getKeyType() == .) {
      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());
    }
    // generate
    generator.initialize(keySize);
    KeyPair pair = generator.generateKeyPair();
    // save
    this.write(keyName.pair.getPrivate().getEncoded());
    this.write(keyName.pair.getPublic().getEncoded());
  }

  
Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.

Parameters:
keyName The name of the key pair.
  public void
  deleteKeyPair(Name keyNamethrows SecurityException
  {
    try {
      // deleteKeyPair is required by an older API which will be changed.
      // For now, call deleteKey.
      deleteKey(keyName);
    } catch (SecurityException ex) {
      // In the deleteKeyPair API, do nothing if the key doesn't exist.
    }
  }

  
Get the public key

Parameters:
keyName The name of public key.
Returns:
The public key.
Throws:
net.named_data.jndn.security.SecurityException
  public final PublicKey
  getPublicKey(Name keyNamethrows SecurityException
  {
    if (!doesKeyExist(keyName.))
      throw new SecurityException("Public key does not exist.");
    // Read the file contents.
    byte[] der = this.read(keyName.);
    return new PublicKey(new Blob(der));
  }

  
Get the private key for this name; internal helper method

Parameters:
keyName The name of the key.
keyType Set keyType[0] to the KeyType.
Returns:
The java.security.PrivateKey.
Throws:
net.named_data.jndn.security.SecurityException
  private PrivateKey
  getPrivateKey(Name keyNameKeyType[] keyTypethrows SecurityException
  {
    if (!doesKeyExist(keyName.))
      throw new SecurityException
        ("FilePrivateKeyStorage: Private key does not exist.");
    // Read the file contents.
    byte[] der = this.read(keyName.);
    // Decode the PKCS #8 DER to find the algorithm OID.
    String oidString = null;
    try {
      DerNode parsedNode = DerNode.parse(ByteBuffer.wrap(der), 0);
      List pkcs8Children = parsedNode.getChildren();
      List algorithmIdChildren = DerNode.getSequence(pkcs8Children, 1).getChildren();
      oidString = ((DerNode.DerOid)algorithmIdChildren.get(0)).toVal().toString();
    }
    catch (DerDecodingException ex) {
      throw new SecurityException("Cannot decode the PKCS #8 private key: " + ex);
    }
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(der);
    if (oidString.equals()) {
      keyType[0] = .;
      try {
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
      }
      catch(InvalidKeySpecException e){
        // Don't expect this to happen.
        throw new SecurityException
          ("FilePrivateKeyStorage: RSA is not supported: " + e.getMessage());
      }
      catch(NoSuchAlgorithmException e){
        // Don't expect this to happen.
        throw new SecurityException
          ("FilePrivateKeyStorage: PKCS8EncodedKeySpec is not supported for RSA: "
                  + e.getMessage());
      }
    }
    else if (oidString.equals()) {
      keyType[0] = .;
      try {
        KeyFactory kf = KeyFactory.getInstance("EC");
        return kf.generatePrivate(spec);
      }
      catch(InvalidKeySpecException e){
        // Don't expect this to happen.
        throw new SecurityException
          ("FilePrivateKeyStorage: EC is not supported: " + e.getMessage());
      }
      catch(NoSuchAlgorithmException e){
        // Don't expect this to happen.
        throw new SecurityException
          ("FilePrivateKeyStorage: PKCS8EncodedKeySpec is not supported for EC: "
                  + e.getMessage());
      }
    }
    else
      throw new SecurityException
        ("FilePrivateKeyStorage::sign: Unrecognized private key OID: " + oidString);
  }

  
Get the symmetric key for this name; internal helper method

Parameters:
keyName
Returns:
The symmetric key.
Throws:
net.named_data.jndn.security.SecurityException
  private final SecretKey
  {
    if (!doesKeyExist(keyName.))
      throw new SecurityException
        ("FilePrivateKeyStorage: Symmetric key does not exist.");
    // Read the file contents.
    byte[] encoded = this.read(keyName.);
    // TODO: Check the key type. Don't assume AES.
    return new SecretKeySpec(encoded"AES");
  }


  
Fetch the private key for keyName and sign the data, returning a signature Blob.

Parameters:
data Pointer the input byte buffer to sign.
keyName The name of the signing key.
digestAlgorithm the digest algorithm.
Returns:
The signature Blob.
Throws:
net.named_data.jndn.security.SecurityException
  public final Blob
  sign(ByteBuffer dataName keyNameDigestAlgorithm digestAlgorithm)
      throws SecurityException
  {
    if (!doesKeyExist(keyName.))
      throw new SecurityException
        ("FilePrivateKeyStorage.sign: private key doesn't exist");
    if (digestAlgorithm != .)
      throw new SecurityException
        ("FilePrivateKeyStorage.sign: Unsupported digest algorithm");
    // Retrieve the private key.
    KeyType[] keyType = new KeyType[1];
    PrivateKey privateKey = getPrivateKey(keyNamekeyType);
    // Sign.
    Signature signature = null;
    if (keyType[0] == .) {
      try {
        signature = Signature.getInstance("SHA256withRSA");
      }
      catch (NoSuchAlgorithmException e) {
        // Don't expect this to happen.
        throw new SecurityException
          ("FilePrivateKeyStorage: The SHA256withRSA algorithm is not supported");
      }
    }
    else if (keyType[0] == .) {
      try {
        signature = Signature.getInstance("SHA256withECDSA");
      }
      catch (NoSuchAlgorithmException e) {
        // Don't expect this to happen.
        throw new SecurityException
          ("FilePrivateKeyStorage: The SHA256withECDSA algorithm is not supported");
      }
    }
    else
      // We don't expect this to happen since getPrivateKey checked it.
      throw new SecurityException
        ("FilePrivateKeyStorage: Unsupported signature key type " + keyType[0]);
    try {
      signature.initSign(privateKey);
    }
    catch (InvalidKeyException exception) {
      throw new SecurityException
        ("FilePrivateKeyStorage: InvalidKeyException: " + exception.getMessage());
    }
    try {
      signature.update(data);
      return new Blob(signature.sign());
    }
    catch (SignatureException exception) {
      throw new SecurityException
        ("FilePrivateKeyStorage: SignatureException: " + exception.getMessage());
    }
  }

  
Decrypt data.

Parameters:
keyName The name of the decrypting key.
data The byte buffer to be decrypted, from its position to its limit.
isSymmetric If true symmetric encryption is used, otherwise asymmetric encryption is used.
Returns:
The decrypted data.
Throws:
net.named_data.jndn.security.SecurityException
  public final Blob
  decrypt(Name keyNameByteBuffer databoolean isSymmetric)
         throws SecurityException
  {
      ("FilePrivateKeyStorage.decrypt is not implemented");
  }

  
Encrypt data.

Parameters:
keyName The name of the encrypting key.
data The byte buffer to be encrypted, from its position to its limit.
isSymmetric If true symmetric encryption is used, otherwise asymmetric encryption is used.
Returns:
The encrypted data.
Throws:
net.named_data.jndn.security.SecurityException
  public final Blob
  encrypt(Name keyNameByteBuffer databoolean isSymmetric)
          throws SecurityException
  {
      ("FilePrivateKeyStorage.encrypt is not implemented");
  }

  
Generate a symmetric key.

Parameters:
keyName The name of the key.
params The parameters of the key.
Throws:
net.named_data.jndn.security.SecurityException
  public final void
  generateKey(Name keyNameKeyParams paramsthrows SecurityException
  {
      ("FilePrivateKeyStorage.generateKey is not implemented");
  }

  
Delete a key by name; checks all KeyClass types

  public final void
  deleteKey(Name keyNamethrows SecurityException
  {
    int deletedFiles = 0;
    for(KeyClass keyClass : KeyClass.values()){
      if (doesKeyExist(keyNamekeyClass)){
        String extension = (String.get(keyClass);
        File file = nameTransform(keyName.toUri(), extension);
        file.delete();
        deletedFiles++;
      }
    }
    if(deletedFiles == 0){
      throw new SecurityException("No key files found to delete");
    }
  }

  
Check if a particular key exists.

Parameters:
keyName The name of the key.
keyClass The class of the key, e.g. KeyClass.PUBLIC, KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
Returns:
True if the key exists, otherwise false.
  public final boolean
  doesKeyExist(Name keyNameKeyClass keyClassthrows SecurityException
  {
    String keyURI = keyName.toUri();
    String extension = (String.get(keyClass);
    if(extension == nullthrow new SecurityException("Unrecognized key class");
    else return nameTransform(keyURIextension).exists();
  }

  
Transform a key name to its hashed file path

Parameters:
keyName
extension
Returns:
The hashed file path.
Throws:
net.named_data.jndn.security.SecurityException
  private File
  nameTransform(String keyNameString extensionthrows SecurityException
  {
    MessageDigest sha256;
    try {
      sha256 = MessageDigest.getInstance("SHA-256");
    }
    catch (NoSuchAlgorithmException exception) {
      // Don't expect this to happen.
      throw new Error
        ("MessageDigest: SHA-256 is not supported: " + exception.getMessage());
    }
    sha256.update(keyName.getBytes());
    byte[] hash = sha256.digest();
    String digest = Common.base64Encode(hash);
    digest = digest.replace('/''%');
    return new File(digest + extension);
  }

  
Write to a key file

Parameters:
keyName
keyClass [PUBLIC, PRIVATE, SYMMETRIC]
data
Throws:
java.io.IOException
net.named_data.jndn.security.SecurityException
  private void
  write(Name keyNameKeyClass keyClassbyte[] datathrows SecurityException{
    String extension = (String.get(keyClass);
    try{
      BufferedWriter writer = new BufferedWriter
        (new FileWriter(nameTransform(keyName.toUri(), extension)));
      try{
        String base64Data = Common.base64Encode(data);
        writer.write(base64Data, 0, base64Data.length());
        writer.flush();
      }
      finally{
        writer.close();
      }
    }
    catch(SecurityException e){
      throw new SecurityException
        ("FilePrivateKeyStorage: Failed to write key: " + e.getMessage());
    }
    catch(IOException e){
      throw new SecurityException
        ("FilePrivateKeyStorage: Failed to write key: " + e.getMessage());
    }
  }

  
Read from a key file

Parameters:
keyName
keyClass [PUBLIC, PRIVATE, SYMMETRIC]
Returns:
The key bytes.
Throws:
java.io.IOException
net.named_data.jndn.security.SecurityException
  private byte[]
  read(Name keyNameKeyClass keyClassthrows SecurityException{
    String extension = (String.get(keyClass);
    StringBuilder contents = new StringBuilder();
    try{
      BufferedReader reader = new BufferedReader
        (new FileReader(nameTransform(keyName.toUri(), extension)));
      // Use "try/finally instead of "try-with-resources" or "using"
      // which are not supported before Java 7.
      try {
        String line = null;
        while ((line = reader.readLine()) != null)
          contents.append(line);
      } finally {
        reader.close();
      }
    }
    catch(SecurityException e) {
      throw new SecurityException
        ("FilePrivateKeyStorage: Failed to read key: " + e.getMessage());
    }
    catch(IOException e) {
      throw new SecurityException
        ("FilePrivateKeyStorage: Failed to read key: " + e.getMessage());
    }
    return Common.base64Decode(contents.toString());
  }
  static private String RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1";
  static private String EC_ENCRYPTION_OID = "1.2.840.10045.2.1";
  private final File keyStorePath_;
  // Use HashMap without generics so it works with older Java compilers.
  private static final HashMap keyTypeMap_;
  static{
     = new HashMap();
    .put(.".pub");
    .put(.".pri");
  }
New to GrepCode? Check out our FAQ X