using System; using System.Collections; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Bcpg.OpenPgp { /// /// Generator for a PGP master and subkey ring. /// This class will generate both the secret and public key rings /// public class PgpKeyRingGenerator { private IList keys = Platform.CreateArrayList(); private string id; private SymmetricKeyAlgorithmTag encAlgorithm; private int certificationLevel; private char[] passPhrase; private bool useSha1; private PgpKeyPair masterKey; private PgpSignatureSubpacketVector hashedPacketVector; private PgpSignatureSubpacketVector unhashedPacketVector; private SecureRandom rand; /// /// Create a new key ring generator using old style checksumming. It is recommended to use /// SHA1 checksumming where possible. /// /// The certification level for keys on this ring. /// The master key pair. /// The id to be associated with the ring. /// The algorithm to be used to protect secret keys. /// The passPhrase to be used to protect secret keys. /// Packets to be included in the certification hash. /// Packets to be attached unhashed to the certification. /// input secured random. public PgpKeyRingGenerator( int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand) : this(certificationLevel, masterKey, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand) { } /// /// Create a new key ring generator. /// /// The certification level for keys on this ring. /// The master key pair. /// The id to be associated with the ring. /// The algorithm to be used to protect secret keys. /// The passPhrase to be used to protect secret keys. /// Checksum the secret keys with SHA1 rather than the older 16 bit checksum. /// Packets to be included in the certification hash. /// Packets to be attached unhashed to the certification. /// input secured random. public PgpKeyRingGenerator( int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand) { this.certificationLevel = certificationLevel; this.masterKey = masterKey; this.id = id; this.encAlgorithm = encAlgorithm; this.passPhrase = passPhrase; this.useSha1 = useSha1; this.hashedPacketVector = hashedPackets; this.unhashedPacketVector = unhashedPackets; this.rand = rand; keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)); } /// Add a subkey to the key ring to be generated with default certification. public void AddSubKey( PgpKeyPair keyPair) { AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector); } /// /// Add a subkey with specific hashed and unhashed packets associated with it and /// default certification. /// /// Public/private key pair. /// Hashed packet values to be included in certification. /// Unhashed packets values to be included in certification. /// public void AddSubKey( PgpKeyPair keyPair, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets) { try { PgpSignatureGenerator sGen = new PgpSignatureGenerator( masterKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1); // // Generate the certification // sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey); sGen.SetHashedSubpackets(hashedPackets); sGen.SetUnhashedSubpackets(unhashedPackets); IList subSigs = Platform.CreateArrayList(); subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey)); keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, passPhrase, useSha1, rand)); } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("exception adding subkey: ", e); } } /// Return the secret key ring. public PgpSecretKeyRing GenerateSecretKeyRing() { return new PgpSecretKeyRing(keys); } /// Return the public key ring that corresponds to the secret key ring. public PgpPublicKeyRing GeneratePublicKeyRing() { IList pubKeys = Platform.CreateArrayList(); IEnumerator enumerator = keys.GetEnumerator(); enumerator.MoveNext(); PgpSecretKey pgpSecretKey = (PgpSecretKey) enumerator.Current; pubKeys.Add(pgpSecretKey.PublicKey); while (enumerator.MoveNext()) { pgpSecretKey = (PgpSecretKey) enumerator.Current; PgpPublicKey k = new PgpPublicKey(pgpSecretKey.PublicKey); k.publicPk = new PublicSubkeyPacket( k.Algorithm, k.CreationTime, k.publicPk.Key); pubKeys.Add(k); } return new PgpPublicKeyRing(pubKeys); } } }