/// <summary>
    /// Returns a specific secret key in the keyring.
    /// </summary>
    /// <param name="openPgp">The <see cref="IOpenPgp"/> implementation.</param>
    /// <param name="keySpecifier">The key ID, fingerprint or any part of a user ID that identifies the keypair; <c>null</c> to use the default key.</param>
    /// <exception cref="KeyNotFoundException">The specified key could not be found on the system.</exception>
    /// <seealso cref="IOpenPgp.Sign"/>
    /// <seealso cref="IOpenPgp.ExportKey"/>
    public static OpenPgpSecretKey GetSecretKey(this IOpenPgp openPgp, string?keySpecifier = null)
    {
        #region Sanity checks
        if (openPgp == null)
        {
            throw new ArgumentNullException(nameof(openPgp));
        }
        #endregion

        var secretKeys = openPgp.ListSecretKeys().ToList();
        if (secretKeys.Count == 0)
        {
            throw new KeyNotFoundException(Resources.UnableToFindSecretKey);
        }

        if (string.IsNullOrEmpty(keySpecifier))
        {
            return(secretKeys[0]);
        }

        try
        {
            long keyID = OpenPgpUtils.ParseKeyID(keySpecifier);
            return(secretKeys.First(x => x.KeyID == keyID));
        }
        catch (FormatException)
        {}
        catch (InvalidOperationException)
        {}

        try
        {
            var fingerprint = OpenPgpUtils.ParseFingerprint(keySpecifier);
            return(secretKeys.First(x => x.Fingerprint.SequenceEqual(fingerprint)));
        }
        catch (FormatException)
        {}
        catch (InvalidOperationException)
        {}

        try
        {
            return(secretKeys.First(x => x.UserID.ContainsIgnoreCase(keySpecifier)));
        }
        catch
        {
            throw new KeyNotFoundException(Resources.UnableToFindSecretKey);
        }
    }
Example #2
0
    /// <summary>
    /// Parses information about a signature from a console line.
    /// </summary>
    /// <param name="line">The console line containing the signature information.</param>
    /// <returns>The parsed signature representation; <c>null</c> if <paramref name="line"/> did not contain any signature information.</returns>
    /// <exception cref="FormatException"><paramref name="line"/> contains incorrectly formatted signature information.</exception>
    private static OpenPgpSignature?ParseSignatureLine(string line)
    {
        const int signatureTypeIndex = 1, fingerprintIndex = 2, timestampIndex = 4, keyIDIndex = 2, errorCodeIndex = 7;

        var signatureParts = line.Split(' ');

        if (signatureParts.Length < signatureTypeIndex + 1)
        {
            return(null);
        }
        switch (signatureParts[signatureTypeIndex])
        {
        case "VALIDSIG":
            if (signatureParts.Length != 12)
            {
                throw new FormatException("Incorrect number of columns in VALIDSIG line.");
            }
            var fingerprint = OpenPgpUtils.ParseFingerprint(signatureParts[fingerprintIndex]);
            return(new ValidSignature(
                       keyID: OpenPgpUtils.FingerprintToKeyID(fingerprint),
                       fingerprint: fingerprint,
                       timestamp: new UnixTime(long.Parse(signatureParts[timestampIndex]))));

        case "BADSIG":
            if (signatureParts.Length < 3)
            {
                throw new FormatException("Incorrect number of columns in BADSIG line.");
            }
            return(new BadSignature(OpenPgpUtils.ParseKeyID(signatureParts[keyIDIndex])));

        case "ERRSIG":
            if (signatureParts.Length != 8)
            {
                throw new FormatException("Incorrect number of columns in ERRSIG line.");
            }
            return(int.Parse(signatureParts[errorCodeIndex]) switch
            {
                9 => new MissingKeySignature(OpenPgpUtils.ParseKeyID(signatureParts[keyIDIndex])),
                _ => new ErrorSignature(OpenPgpUtils.ParseKeyID(signatureParts[keyIDIndex]))
            });