/// <summary> /// Finds a subkey (or the primary key) with the given keyid /// and returns it. Returns null if the the fitting key has /// not been found. /// </summary> /// <remarks>If the public key has been revoked, it is ignored /// and NOT found by this function!!!</remarks> /// <param name="lKeyID">The keyid to be sought in the transportable /// public key.</param> /// <returns>The subkey (or the primary key) with the given keyid. /// Null if the the fitting key has not been found.</returns> public PublicKeyPacket FindKey(ulong lKeyID) { if (pkpPrimaryKey.KeyID == lKeyID) { return(pkpPrimaryKey); } IEnumerator ieSubkeys = alSubkeys.GetEnumerator(); while (ieSubkeys.MoveNext()) { CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current; // The subkey has been revoced if (cpsKey.RevocationSignature != null) { continue; } PublicKeyPacket pkpKey = cpsKey.Subkey; if (pkpKey.KeyID == lKeyID) { return(pkpKey); } } return(null); }
/// <summary> /// Parses the radix64 encoded representation of a transportable public /// key given as an argument to populate the parameters of this. /// </summary> /// <remarks>No remarks</remarks> /// <param name="strRadix64">Radix64 representation of an transportable /// public key</param> /// <exception cref="System.ArgumentException">Throws an /// ArgumentException if the radix64 string given as a parameter is /// not an transportable public key.</exception> public void Parse(string strRadix64) { Packet[] pPackets = Packet.ParsePackets(strRadix64); int nCurrentPacket = 0; int nUserIDCounter = 0; try { // First we expect a PublicKeyPacket if (!(pPackets[0] is PublicKeyPacket)) { throw(new ArgumentException("The given packet is not in the required transportable public key format!")); } this.PrimaryKey = (PublicKeyPacket)pPackets[nCurrentPacket++]; // Next we expect zero or more revocation signatures while ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is SignaturePacket)) { SignaturePacket spRevocation = (SignaturePacket)pPackets[nCurrentPacket++]; if (spRevocation.SignatureType != SignatureTypes.KeyRevocationSignature) { throw(new ArgumentException("The given packet is not in the required transportable public key format!")); } this.RevocationSignatures.Add(spRevocation); } // Next in queue must be one or more UserID Packets while ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is UserIDPacket)) { nUserIDCounter++; CertifiedUserID cuiUserID = new CertifiedUserID(); UserIDPacket uipUserID = (UserIDPacket)pPackets[nCurrentPacket++]; cuiUserID.UserID = uipUserID; // For every UserIDPacket we expect zero or more Signatures (Certificates) while ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is SignaturePacket)) { SignaturePacket spCertificate = (SignaturePacket)pPackets[nCurrentPacket++]; if ((spCertificate.SignatureType != SignatureTypes.UserIDSignature) && (spCertificate.SignatureType != SignatureTypes.UserIDSignature_CasualVerification) && (spCertificate.SignatureType != SignatureTypes.UserIDSignature_NoVerification) && (spCertificate.SignatureType != SignatureTypes.UserIDSignature_PositivVerification)) { throw(new ArgumentException("The given packet is not in the required transportable public key format!")); } cuiUserID.Certificates.Add(spCertificate); } this.Certifications.Add(cuiUserID); } // There was no UserIDPacket. This is fatal!!! if (nUserIDCounter == 0) { throw(new ArgumentException("The given packet is not in the required transportable public key format!")); } // Finally we have zero or more subkeys while ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is PublicKeyPacket)) { PublicKeyPacket pkpSubKey = (PublicKeyPacket)pPackets[nCurrentPacket++]; CertifiedPublicSubkey cpsSubKey = new CertifiedPublicSubkey(); cpsSubKey.Subkey = pkpSubKey; if ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is SignaturePacket)) { SignaturePacket spKeySignature = (SignaturePacket)pPackets[nCurrentPacket++]; if (spKeySignature.SignatureType == SignatureTypes.SubkeyBindingSignature) { cpsSubKey.KeyBindingSignature = spKeySignature; } else if (spKeySignature.SignatureType == SignatureTypes.SubkeyRevocationSignature) { cpsSubKey.RevocationSignature = spKeySignature; } } else { throw(new ArgumentException("The given packet is not in the required transportable public key format!")); } if (nCurrentPacket < pPackets.Length) { if (pPackets[nCurrentPacket] is SignaturePacket) { SignaturePacket spSubkeyRev = (SignaturePacket)pPackets[nCurrentPacket++]; cpsSubKey.RevocationSignature = spSubkeyRev; } } this.SubKeys.Add(cpsSubKey); } } catch (System.IndexOutOfRangeException) { if (nUserIDCounter == 0) { throw(new ArgumentException("The given packet is not in the required transportable public key format!")); } } }
/// <summary> /// Finds a subkey (or the primary key) that fits to the given /// requirements (meaning it must be supposed to be used for /// the given action, which can be either signing or encryption). /// If more than just one keys fullfill the requirements, the one /// with the newer creationdate is used. /// </summary> /// <remarks>No remarks</remarks> /// <param name="aaAction">The action (signing or encrypting) for /// which the key should be used</param> /// <returns>Returns a public key packet fullfilling the given /// requirements (the action) or null, if it did not find such /// a key.</returns> public PublicKeyPacket FindKey(AsymActions aaAction) { DateTime dtCandidateTime = DateTime.Now; PublicKeyPacket pkpCandidate = new PublicKeyPacket(); bool bFound = false; // First check the primary Key if (aaAction == AsymActions.Encrypt) { if (pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign || pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGamal_Encrypt_Only || pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Only || pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) { dtCandidateTime = pkpPrimaryKey.TimeCreated; bFound = true; pkpCandidate = pkpPrimaryKey; } } else if (aaAction == AsymActions.Sign) { if (pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign || pkpPrimaryKey.Algorithm == AsymAlgorithms.DSA || pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Sign_Only || pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) { dtCandidateTime = pkpPrimaryKey.TimeCreated; bFound = true; pkpCandidate = pkpPrimaryKey; } } // Now check the subkeys IEnumerator ieSubkeys = alSubkeys.GetEnumerator(); while (ieSubkeys.MoveNext()) { CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current; // The subkey has been revoced if (cpsKey.RevocationSignature != null) { continue; } PublicKeyPacket pkpKey = cpsKey.Subkey; if (aaAction == AsymActions.Encrypt) { if (pkpKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign || pkpKey.Algorithm == AsymAlgorithms.ElGamal_Encrypt_Only || pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Only || pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) { if ((bFound && dtCandidateTime < pkpKey.TimeCreated) || (!bFound)) { dtCandidateTime = pkpKey.TimeCreated; bFound = true; pkpCandidate = pkpKey; } } } else if (aaAction == AsymActions.Sign) { if (pkpKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign || pkpKey.Algorithm == AsymAlgorithms.DSA || pkpKey.Algorithm == AsymAlgorithms.RSA_Sign_Only || pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) { if ((bFound && dtCandidateTime < pkpKey.TimeCreated) || (!bFound)) { dtCandidateTime = pkpKey.TimeCreated; bFound = true; pkpCandidate = pkpKey; } } } } if (bFound) { return(pkpCandidate); } return(null); }
/// <summary> /// Generates the transportable public key out of the properties /// in this. /// </summary> /// <remarks>No remarks</remarks> /// <returns>Returns a byte array containing the openpgp encoded /// representation of the transportable public key.</returns> public byte[] Generate() { byte[] bPrimaryKey = this.PrimaryKey.Generate(); //Revocation signatures int iLength = 0; IEnumerator ieRevocations = this.RevocationSignatures.GetEnumerator(); while (ieRevocations.MoveNext()) { if (ieRevocations.Current is SignaturePacket) { iLength += ((SignaturePacket)ieRevocations.Current).Generate().Length; } } byte[] bRevocations = new byte[iLength]; ieRevocations = this.RevocationSignatures.GetEnumerator(); int iPosition = 0; while (ieRevocations.MoveNext()) { if (ieRevocations.Current is SignaturePacket) { byte[] bRev = ((SignaturePacket)ieRevocations.Current).Generate(); Array.Copy(bRev, 0, bRevocations, iPosition, bRev.Length); iPosition += bRev.Length; } } //Certificates iLength = 0; IEnumerator ieCertificates = this.Certifications.GetEnumerator(); while (ieCertificates.MoveNext()) { if (ieCertificates.Current is CertifiedUserID) { CertifiedUserID cuiID = (CertifiedUserID)ieCertificates.Current; iLength += cuiID.Generate().Length; } } byte[] bCertificates = new byte[iLength]; iPosition = 0; ieCertificates = this.Certifications.GetEnumerator(); while (ieCertificates.MoveNext()) { if (ieCertificates.Current is CertifiedUserID) { CertifiedUserID cuiID = (CertifiedUserID)ieCertificates.Current; byte[] bCert = cuiID.Generate(); Array.Copy(bCert, 0, bCertificates, iPosition, bCert.Length); iPosition += bCert.Length; } } //SubKeys iLength = 0; IEnumerator ieSubkeys = this.SubKeys.GetEnumerator(); while (ieSubkeys.MoveNext()) { if (ieSubkeys.Current is CertifiedPublicSubkey) { CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current; iLength += cpsKey.Generate().Length; } } byte[] bSubkeys = new byte[iLength]; iPosition = 0; ieSubkeys = this.SubKeys.GetEnumerator(); while (ieSubkeys.MoveNext()) { if (ieSubkeys.Current is CertifiedPublicSubkey) { CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current; byte[] bKey = cpsKey.Generate(); Array.Copy(bKey, 0, bSubkeys, iPosition, bKey.Length); iPosition += bKey.Length; } } byte[] bData = new byte[bPrimaryKey.Length + bRevocations.Length + bCertificates.Length + bSubkeys.Length]; iPosition = 0; Array.Copy(bPrimaryKey, bData, bPrimaryKey.Length); iPosition = bPrimaryKey.Length; Array.Copy(bRevocations, 0, bData, iPosition, bRevocations.Length); iPosition += bRevocations.Length; Array.Copy(bCertificates, 0, bData, iPosition, bCertificates.Length); iPosition += bCertificates.Length; Array.Copy(bSubkeys, 0, bData, iPosition, bSubkeys.Length); return(bData); }