Ejemplo n.º 1
0
 /// <summary>
 /// Verifies that a digital signature is valid by calculating the hash value of the specified data
 /// using the specified hash algorithm and padding, and comparing it to the provided signature.
 /// </summary>
 /// <param name="data">The data to sign.</param>
 /// <param name="signature">The signature data to be verified.</param>
 /// <returns>true if the signature is valid; otherwise, false.</returns>
 public bool Verify(byte[] data, byte[] signature)
 {
     return(ListExtensions.Equals(Sign(data), signature));
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Verifies that a digital signature is valid by calculating the hash value of the specified data
 /// using the specified hash algorithm and padding, and comparing it to the provided signature.
 /// </summary>
 /// <param name="data">The data to sign.</param>
 /// <param name="signature">The signature data to be verified.</param>
 /// <returns>true if the signature is valid; otherwise, false.</returns>
 public bool Verify(byte[] data, byte[] signature)
 {
     return(verify != null
         ? verify(data, signature, secretBytes)
         : ListExtensions.Equals(sign(data, secretBytes), signature));
 }
Ejemplo n.º 3
0
    /// <summary>
    /// Parses the parameters from OpenSSL RSA key (PEM Base64) or the RSA parameters XML string.
    /// </summary>
    /// <param name="key">The OpenSSL RSA key string (PEM Base64) or the RSA parameters XML string.</param>
    /// <returns>The RSA parameters; or null, if parse failed.</returns>
    public static RSAParameters?Parse(string key)
    {
        if (string.IsNullOrWhiteSpace(key))
        {
            return(null);
        }
        key = key.Trim();
        if (key.IndexOf("<") == 0 && key.LastIndexOf(">") == key.Length - 1)
        {
            var xml = XElement.Parse(key);
            if (xml == null)
            {
                return(null);
            }
            var p = new RSAParameters();
            foreach (var ele in xml.Elements())
            {
                if (string.IsNullOrWhiteSpace(ele?.Value))
                {
                    continue;
                }
                var chars = Convert.FromBase64String(ele.Value);
                switch (ele.Name?.LocalName?.ToLowerInvariant())
                {
                case "modulus":
                    p.Modulus = chars;
                    break;

                case "exponent":
                    p.Exponent = chars;
                    break;

                case "p":
                    p.P = chars;
                    break;

                case "q":
                    p.Q = chars;
                    break;

                case "dp":
                    p.DP = chars;
                    break;

                case "dq":
                    p.DQ = chars;
                    break;

                case "inverseq":
                    p.InverseQ = chars;
                    break;

                case "d":
                    p.D = chars;
                    break;
                }
            }

            if (p.Modulus == null || p.Modulus.Length == 0 || p.Exponent == null || p.Exponent.Length == 0)
            {
                return(null);
            }
            return(p);
        }

        var lines = key.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

        if (lines.Length == 0)
        {
            return(null);
        }
        var isPrivate = true;
        var firstLine = lines[0].Trim();

        if (lines.Length == 1)
        {
            key = firstLine;
        }
        else if (firstLine.IndexOf("ssh-rsa ") == 0)
        {
            isPrivate = false;
            key       = string.Join(string.Empty, lines).Trim();
            if (key.Length < 16)
            {
                return(null);
            }
            key = key.Substring(8);
            var blankPos = key.IndexOf(' ');
            if (blankPos > 0)
            {
                key = key.Substring(0, blankPos);
            }
        }
        else if (lines.Length == 2)
        {
            isPrivate = firstLine.IndexOf("PRIVATE KEY") >= 0;
            key       = lines[1];
        }
        else
        {
            isPrivate = firstLine.IndexOf(" PRIVATE KEY") > 0 || firstLine.IndexOf("PRIVATE KEY") == 0;
            key       = string.Join(string.Empty, lines.Skip(1).Take(lines.Length - 2));
        }

        using (var stream = new MemoryStream(Convert.FromBase64String(key)))
        {
            using (var reader = new BinaryReader(stream))
            {
                if (isPrivate)
                {
                    var twoBytes = reader.ReadUInt16();
                    if (twoBytes == 0x8130)
                    {
                        reader.ReadByte();
                    }
                    else if (twoBytes == 0x8230)
                    {
                        reader.ReadInt16();
                    }
                    else
                    {
                        return(null);
                    }
                    if (!AreSame(reader, verPem))
                    {
                        return(null);
                    }

                    // For PKCS8.
                    if (reader.BaseStream.Position + seqOID.Length < reader.BaseStream.Length)
                    {
                        var isPkcs8 = true;
                        var i       = 0;
                        for (; i < seqOID.Length; i++)
                        {
                            if (seqOID[i] == reader.ReadByte())
                            {
                                continue;
                            }
                            isPkcs8 = false;
                            break;
                        }

                        if (isPkcs8)
                        {
                            GetIntegerSize(reader, 0x04);
                            GetIntegerSize(reader, 0x30);
                            if (!AreSame(reader, verPem))
                            {
                                return(null);
                            }
                        }
                        else
                        {
                            i++;
                            reader.BaseStream.Seek(-i, SeekOrigin.Current);
                        }
                    }

                    return(new RSAParameters
                    {
                        Modulus = reader.ReadBytes(GetIntegerSize(reader)),
                        Exponent = reader.ReadBytes(GetIntegerSize(reader)),
                        D = reader.ReadBytes(GetIntegerSize(reader)),
                        P = reader.ReadBytes(GetIntegerSize(reader)),
                        Q = reader.ReadBytes(GetIntegerSize(reader)),
                        DP = reader.ReadBytes(GetIntegerSize(reader)),
                        DQ = reader.ReadBytes(GetIntegerSize(reader)),
                        InverseQ = reader.ReadBytes(GetIntegerSize(reader))
                    });
                }
                else
                {
                    var twoBytes = reader.ReadUInt16();
                    if (twoBytes == 0x8130) // Data read as little endian order (actual data order for Sequence is 30 81).
                    {
                        reader.ReadByte();  // Advance 1 byte.
                    }
                    else if (twoBytes == 0x8230)
                    {
                        reader.ReadInt16(); // Advance 2 bytes.
                    }
                    else
                    {
                        return(null);
                    }

                    var seq = reader.ReadBytes(15);          // Read the Sequence OID.
                    if (!ListExtensions.Equals(seq, seqOID)) // Make sure Sequence for OID is correct.
                    {
                        return(null);
                    }

                    twoBytes = reader.ReadUInt16();
                    if (twoBytes == 0x8103) // Data read as little endian order (actual data order for Bit String is 03 81).
                    {
                        reader.ReadByte();  // Advance 1 byte.
                    }
                    else if (twoBytes == 0x8203)
                    {
                        reader.ReadInt16(); // Advance 2 bytes.
                    }
                    else
                    {
                        return(null);
                    }

                    var testByte = reader.ReadByte();
                    if (testByte != 0x00) // Expect null byte next.
                    {
                        return(null);
                    }

                    twoBytes = reader.ReadUInt16();
                    if (twoBytes == 0x8130) // Data read as little endian order (actual data order for Sequence is 30 81).
                    {
                        reader.ReadByte();  // Advance 1 byte.
                    }
                    else if (twoBytes == 0x8230)
                    {
                        reader.ReadInt16(); // Advance 2 bytes.
                    }
                    else
                    {
                        return(null);
                    }

                    twoBytes = reader.ReadUInt16();
                    byte lowByte  = 0x00;
                    byte highByte = 0x00;

                    if (twoBytes == 0x8102)          // Data read as little endian order (actual data order for Integer is 02 81).
                    {
                        lowByte = reader.ReadByte(); // Read next bytes which is bytes in modulus.
                    }
                    else if (twoBytes == 0x8202)
                    {
                        highByte = reader.ReadByte();   // Advance 2 bytes.
                        lowByte  = reader.ReadByte();
                    }
                    else
                    {
                        return(null);
                    }

                    byte[] modInt    = { lowByte, highByte, 0x00, 0x00 }; // Reverse byte order since asn.1 key uses big endian order.
                    var    modsize   = BitConverter.ToInt32(modInt, 0);
                    var    firstByte = reader.PeekChar();
                    if (firstByte == 0x00)
                    {                      // Don't include it if the first byte (highest order) of modulus is zero.
                        reader.ReadByte(); // Skip this null byte.
                        modsize -= 1;      // Reduce modulus buffer size by 1.
                    }

                    var modulus = reader.ReadBytes(modsize); // Read the modulus bytes.
                    if (reader.ReadByte() != 0x02)           // Expect an Integer for the exponent data.
                    {
                        return(null);
                    }
                    var expBytes = (int)reader.ReadByte();  // Should only need one byte for actual exponent data (for all useful values).
                    var exponent = reader.ReadBytes(expBytes);

                    // Create RSACryptoServiceProvider instance and initialize with public key.
                    return(new RSAParameters
                    {
                        Modulus = modulus,
                        Exponent = exponent
                    });
                }
            }
        }
    }