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

com.jsuereth.pgp.PublicKey.scala Maven / Gradle / Ivy

The newest version!
package com.jsuereth.pgp

import java.io._
import org.bouncycastle.bcpg._
import org.bouncycastle.openpgp._
import java.security.SecureRandom

/** This class represents a public PGP key. It can be used to encrypt messages for a person and validate that messages were signed correctly. */
class PublicKey(val nested: PGPPublicKey) extends PublicKeyLike with StreamingSaveable {
  /** The identifier for this key. */
  def keyID = nested.getKeyID
  
  def bitStrength = nested.getBitStrength
  def creationTime = nested.getCreationTime
  def fingerprint = nested.getFingerprint
  def isRevoked = nested.isRevoked
  def algorithm = nested.getAlgorithm
  def algorithmName = nested.getAlgorithm match {
    case PublicKeyAlgorithmTags.RSA_ENCRYPT |
         PublicKeyAlgorithmTags.RSA_GENERAL |
         PublicKeyAlgorithmTags.RSA_SIGN        => "RSA"
    case PublicKeyAlgorithmTags.DSA             => "DSA"
    case PublicKeyAlgorithmTags.EC              => "EC"
    case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT |       
         PublicKeyAlgorithmTags.ELGAMAL_GENERAL => "ElGamal"
    case PublicKeyAlgorithmTags.ECDSA           => "ECDSA"
    case _ => "Unknown"
  }
  /** Returns the userIDs associated with this public key. */
  object userIDs extends Traversable[String] {
    def foreach[U](f: String => U) = {
      val i = nested.getUserIDs
      while(i.hasNext) f(i.next.toString)
    }
  }
  
  object signatures extends Traversable[Signature] {
    override def foreach[U](f: Signature => U): Unit = {
      val i = nested.getSignatures()
      while(i.hasNext) {
        f(Signature(i.next.asInstanceOf[PGPSignature]))
      }
    }
  }
  
  def signaturesForId(id: String): Traversable[Signature] = new Traversable[Signature] {
    override def foreach[U](f: Signature => U): Unit = {
      val i = nested.getSignaturesForID(id)
      while(i.hasNext) {
        f(Signature(i.next.asInstanceOf[PGPSignature]))
      }
    }
  }
  
  def directKeySignatures: Traversable[Signature] =
    signatures.view filter (_.signatureType == PGPSignature.DIRECT_KEY)
  
  def verifyMessageStream(input: InputStream, output: OutputStream): Boolean =
    verifyMessageStreamHelper(input,output) { id =>
      assert(id == keyID)
      nested
    }
  def verifySignatureStreams(msg: InputStream, signature: InputStream): Boolean = 
    verifySignatureStreamsHelper(msg,signature) { id =>
      if(keyID != id) error("Signature is not for this key.  %x != %x".format(id, keyID))
      nested
    }
  /** Encrypts a file such that only the secret key associated with this public key can decrypt. */
  def encryptFile(input: File, output: File): Unit = {
    val in = new FileInputStream(input)
    val out = new FileOutputStream(output)
    try encrypt(in, out, input.getName, input.length, new java.util.Date(input.lastModified))
    finally {
      in.close()
      out.close()
    }
  }
  /** Encrypts a string such that only the secret key associated with this public key could decrypt. */
  def encryptString(input: String): String = {
    val bytes = input.getBytes
    val in = new java.io.ByteArrayInputStream(bytes)
    val out = new java.io.ByteArrayOutputStream
    // TODO - better errors...
    try encrypt(in, out, "", bytes.length, new java.util.Date()) finally {
      in.close()
      out.close()
    }
    out.toString(java.nio.charset.Charset.defaultCharset.name)
  }
  
  def encrypt(
      data: InputStream, 
      output: OutputStream, 
      fileName: String, 
      size: Long, 
      lastMod: java.util.Date = new java.util.Date): Unit = {
    val aout = new ArmoredOutputStream(output)
    // TODO - Compress on the way into bytes
    val bytes = Array.empty[Byte]
    val encGen = new PGPEncryptedDataGenerator(
                SymmetricKeyAlgorithmTags.CAST5, 
                true, 
                new SecureRandom(), 
                "BC")
    encGen.addMethod(nested)
    val cOut = encGen.open(aout, new Array[Byte](1024))
    val lit = new PGPLiteralDataGenerator
    val lOut = lit.open(cOut, PGPLiteralDataGenerator.BINARY, fileName, size, lastMod)
    val buffer = new Array[Byte](1024)
    def read(): Unit = data.read(buffer) match {
      case n if n > 0 => lOut.write(buffer, 0, n); read()
      case _          => ()
    }
    read()
    lit.close()
    cOut.close()
    aout.close()
    data.close() 
  }
  
  def saveTo(output: OutputStream): Unit = {
    val armoredOut = new ArmoredOutputStream(output)   
    nested.encode(armoredOut)
    armoredOut.close()
  }
  override lazy val toString = "PublicKey(%x, %s, %s@%d)".format(keyID, userIDs.mkString(","), algorithmName, bitStrength)
}
object PublicKey {
  def apply(nested: PGPPublicKey) = new PublicKey(nested)
  implicit def unwrap(key: PublicKey) = key.nested
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy