/// <summary> /// Verifies that a digital signature is valid by determining the hash value /// in the signature using the provided public key and comparing it to the hash /// value of the provided data. /// </summary> /// <param name="inputStream">The data that was signed.</param> /// <param name="signature">The signature data to be verified.</param> /// <param name="rsaProvider">The RSA crypto service provider.</param> /// <param name="hashAlgorithm">The hash algorithm to use to create the hash value.</param> /// <returns>True if the signature is valid; otherwise, false.</returns> public bool VerifyData(Stream inputStream, byte[] signature, RSACryptoServiceProvider rsaProvider, Nequeo.Cryptography.HashcodeType hashAlgorithm = HashcodeType.SHA512) { Stream signatureInput = null; try { // Export the signer public key parameters. RSAParameters rsaPublicKeySignerParam = rsaProvider.ExportParameters(false); Key.Crypto.Parameters.RsaKeyParameters rsaPublicKeySigner = new Key.Crypto.Parameters.RsaKeyParameters( false, new Key.Math.BigInteger(1, rsaPublicKeySignerParam.Modulus), new Key.Math.BigInteger(1, rsaPublicKeySignerParam.Exponent) ); signatureInput = new MemoryStream(signature); signatureInput = Key.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(signatureInput); // Get the public key. Key.Bcpg.OpenPgp.PgpPublicKey publicKey = new Key.Bcpg.OpenPgp.PgpPublicKey(Key.Bcpg.PublicKeyAlgorithmTag.RsaGeneral, rsaPublicKeySigner, DateTime.UtcNow); Key.Bcpg.OpenPgp.PgpObjectFactory pgpFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(signatureInput); Key.Bcpg.OpenPgp.PgpSignatureList signatureList = null; Key.Bcpg.OpenPgp.PgpObject pgpObject = pgpFact.NextPgpObject(); // If the message is compressed. if (pgpObject is Key.Bcpg.OpenPgp.PgpCompressedData) { // Get the compression object. Key.Bcpg.OpenPgp.PgpCompressedData compressedData = (Key.Bcpg.OpenPgp.PgpCompressedData)pgpObject; pgpFact = new Key.Bcpg.OpenPgp.PgpObjectFactory(compressedData.GetDataStream()); signatureList = (Key.Bcpg.OpenPgp.PgpSignatureList)pgpFact.NextPgpObject(); } else { // Get the message list. signatureList = (Key.Bcpg.OpenPgp.PgpSignatureList)pgpObject; } // Load the public key into the pgp signer. Key.Bcpg.OpenPgp.PgpSignature pgpSignature = signatureList[0]; pgpSignature.InitVerify(publicKey); int ch; while ((ch = inputStream.ReadByte()) >= 0) { // Update the generator. pgpSignature.Update((byte)ch); } // Verify the signature. if (pgpSignature.Verify()) { // signature verified. return(true); } else { // signature verification failed. return(false); } } catch (Exception) { throw; } finally { if (signatureInput != null) { signatureInput.Close(); } } }
public PgpSignatureList( PgpSignature sig) { this.sigs = new PgpSignature[] { sig }; }
/// <summary> /// Computes the hash value of the specified input stream using the specified /// hash algorithm, and signs the resulting hash value. /// </summary> /// <param name="inputStream">The input data for which to compute the hash.</param> /// <param name="rsaProvider">The RSA crypto service provider.</param> /// <param name="keyID">The unique key id of the public secret key pair.</param> /// <param name="hashAlgorithm">The hash algorithm to use to create the hash value.</param> /// <returns>The signature for the specified data.</returns> public byte[] SignData(Stream inputStream, RSACryptoServiceProvider rsaProvider, long keyID, Nequeo.Cryptography.HashcodeType hashAlgorithm = HashcodeType.SHA512) { MemoryStream output = null; Key.Bcpg.BcpgOutputStream pgpOutput = null; try { int ch; output = new MemoryStream(); // Export the signer private key parameters. RSAParameters rsaPrivateKeySignerParam = rsaProvider.ExportParameters(true); Key.Crypto.Parameters.RsaPrivateCrtKeyParameters rsaPrivateKeySigner = new Key.Crypto.Parameters.RsaPrivateCrtKeyParameters( new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Modulus), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Exponent), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.D), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.P), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.Q), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.DP), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.DQ), new Key.Math.BigInteger(1, rsaPrivateKeySignerParam.InverseQ) ); // Get the private key. Key.Bcpg.OpenPgp.PgpPrivateKey privateKey = new Key.Bcpg.OpenPgp.PgpPrivateKey(rsaPrivateKeySigner, keyID); // Create a signature generator. Key.Bcpg.OpenPgp.PgpSignatureGenerator signatureGenerator = new Key.Bcpg.OpenPgp.PgpSignatureGenerator(Key.Bcpg.PublicKeyAlgorithmTag.RsaGeneral, GetHashAlgorithm(hashAlgorithm)); signatureGenerator.InitSign(Key.Bcpg.OpenPgp.PgpSignature.BinaryDocument, privateKey); // Create the output stream. pgpOutput = new Key.Bcpg.BcpgOutputStream(output); // Read the input stream. while ((ch = inputStream.ReadByte()) >= 0) { // Update the generator. signatureGenerator.Update((byte)ch); } // Write the hash to the output stream. Key.Bcpg.OpenPgp.PgpSignature signature = signatureGenerator.Generate(); signature.Encode(pgpOutput); // Return the signed value. return(output.ToArray()); } catch (Exception) { throw; } finally { if (output != null) { output.Close(); } if (pgpOutput != null) { pgpOutput.Close(); } } }
/// <summary>Return the next object in the stream, or null if the end is reached.</summary> /// <exception cref="IOException">On a parse error</exception> public PgpObject NextPgpObject() { PacketTag tag = bcpgIn.NextPacketTag(); if ((int)tag == -1) { return(null); } switch (tag) { case PacketTag.Signature: { IList l = Platform.CreateArrayList(); while (bcpgIn.NextPacketTag() == PacketTag.Signature) { try { l.Add(new PgpSignature(bcpgIn)); } catch (PgpException e) { throw new IOException("can't create signature object: " + e); } } PgpSignature[] sigs = new PgpSignature[l.Count]; for (int i = 0; i < l.Count; ++i) { sigs[i] = (PgpSignature)l[i]; } return(new PgpSignatureList(sigs)); } case PacketTag.SecretKey: try { return(new PgpSecretKeyRing(bcpgIn)); } catch (PgpException e) { throw new IOException("can't create secret key object: " + e); } case PacketTag.PublicKey: return(new PgpPublicKeyRing(bcpgIn)); // TODO Make PgpPublicKey a PgpObject or return a PgpPublicKeyRing // case PacketTag.PublicSubkey: // return PgpPublicKeyRing.ReadSubkey(bcpgIn); case PacketTag.CompressedData: return(new PgpCompressedData(bcpgIn)); case PacketTag.LiteralData: return(new PgpLiteralData(bcpgIn)); case PacketTag.PublicKeyEncryptedSession: case PacketTag.SymmetricKeyEncryptedSessionKey: return(new PgpEncryptedDataList(bcpgIn)); case PacketTag.OnePassSignature: { IList l = Platform.CreateArrayList(); while (bcpgIn.NextPacketTag() == PacketTag.OnePassSignature) { try { l.Add(new PgpOnePassSignature(bcpgIn)); } catch (PgpException e) { throw new IOException("can't create one pass signature object: " + e); } } PgpOnePassSignature[] sigs = new PgpOnePassSignature[l.Count]; for (int i = 0; i < l.Count; ++i) { sigs[i] = (PgpOnePassSignature)l[i]; } return(new PgpOnePassSignatureList(sigs)); } case PacketTag.Marker: return(new PgpMarker(bcpgIn)); case PacketTag.Experimental1: case PacketTag.Experimental2: case PacketTag.Experimental3: case PacketTag.Experimental4: return(new PgpExperimental(bcpgIn)); } throw new IOException("unknown object in stream " + bcpgIn.NextPacketTag()); }