/// <summary> /// Initializes a new instance of the <see cref="RsaCertificate"/> class /// for a signed certificate. This constructor is intended to be used /// when creating a new certificate from within an application. /// </summary> /// <param name="parameters">The cryptographic RSA parameters. Be sure not to /// include any private parameters.</param> /// <param name="embeddedData">The embedded data or null if none.</param> /// <param name="signCertificateCallback">The callback method to be invoked after /// the hash value was calculated from the cryptographic RSA parameters in order /// to get the signature determined from that hash value.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="signature"/> is null.</exception> public RsaCertificate(RSAParameters parameters, IEnumerable <byte> embeddedData, Func <IHash, RsaSignature> signCertificateCallback) { if (signCertificateCallback == null) { throw new ArgumentNullException(nameof(signCertificateCallback)); } this.parameters = parameters; this.EmbeddedData = embeddedData?.ToArray(); // Compute preliminary hash which does not include a signature. this.Hash = Helpers.ComputeRsaHash( rsaParameters: parameters, includePrivateParameters: false, embeddedData: embeddedData); this.Signature = signCertificateCallback.Invoke(this.Hash); // Re-compute hash which now includes the signature. this.HashWithSignature = Helpers.ComputeRsaHashWithSignature( rsaParameters: parameters, includePrivateParameters: false, embeddedData: embeddedData, signature: this.Signature); }
/// <summary> /// Signs a certificate by its hash value. /// </summary> /// <param name="certificate">The certificate to sign.</param> /// <returns>The signed certificate.</returns> /// <exception cref="ArgumentNullException">Thrown if /// <paramref name="certificate"/> is null.</exception> public RsaCertificate Sign(RsaCertificate certificate) { if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } // Create copy of RSA cryptographic parameters before creating the certificate // with these data to avoid manipulation of references of cryptographic parameters // via reflection or such. var rsaParameters = certificate.CreateRsa().ExportParameters(false); // Replace certificate by one with the same cryptographic RSA parameters // but no signature. var unsignedCertificate = new RsaCertificate(rsaParameters); var signature = new RsaSignature( signerCertificateHash: this.DeriveCertificate().Hash, signature: this.rsa.SignHash( unsignedCertificate.Hash.Hash.ToArray(), unsignedCertificate.Hash.Name, RSASignaturePadding.Pkcs1)); var signedCertificate = new RsaCertificate(rsaParameters, this.EmbeddedData, signature); return(signedCertificate); }
/// <summary> /// Initializes a new instance of the <see cref="RsaKey"/> class. /// </summary> /// <param name="parameters">The cryptographic RSA parameters.</param> /// <param name="signature">The cryptographic RSA signature.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="signature"/> is null.</exception> public RsaKey(RSAParameters parameters, RsaSignature signature) { this.parameters = parameters; this.signature = signature ?? throw new ArgumentNullException(nameof(signature)); this.Hash = Helpers.ComputeRsaHash( rsaParameters: parameters, includePrivateParameters: false, embeddedData: null); this.rsa = this.CreateRsa(); }
/// <summary> /// Initializes a new instance of the <see cref="RsaKey"/> class. /// </summary> /// <param name="parameters">The cryptographic RSA parameters.</param> /// <param name="embeddedData">The embedded data or null if none.</param> /// <param name="signature">The cryptographic RSA signature.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="signature"/> is null.</exception> public RsaKey(RSAParameters parameters, IEnumerable <byte> embeddedData, RsaSignature signature) { this.parameters = parameters; this.EmbeddedData = embeddedData?.ToArray(); this.signature = signature ?? throw new ArgumentNullException(nameof(signature)); this.Hash = Helpers.ComputeRsaHash( rsaParameters: parameters, includePrivateParameters: false, embeddedData: embeddedData); this.rsa = this.CreateRsa(); }
/// <summary> /// Initializes a new instance of the <see cref="RsaCertificate"/> class /// for a signed certificate. This constructor is intended to be used /// when loading an existing certificate from a file or the like. /// </summary> /// <param name="parameters">The cryptographic RSA parameters. Be sure not to /// include any private parameters.</param> /// <param name="signature">The RSA signature.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="signature"/> is null.</exception> public RsaCertificate(RSAParameters parameters, RsaSignature signature) { this.parameters = parameters; this.Signature = signature ?? throw new ArgumentNullException(nameof(signature)); this.Hash = Helpers.ComputeRsaHash( rsaParameters: parameters, includePrivateParameters: false, embeddedData: null); this.HashWithSignature = Helpers.ComputeRsaHashWithSignature( rsaParameters: parameters, includePrivateParameters: false, embeddedData: null, signature: this.Signature); }
/// <summary> /// Computes the hash of certain parameters used in RSA certificates and keys. /// </summary> /// <param name="rsaParameters">The cryptographic RSA parameters.</param> /// <param name="includePrivateParameters">true to include cryptographic RSA private parameters, /// false to include only public ones.</param> /// <param name="embeddedData">The embedded data to consider for computing /// the hash.</param> /// <param name="signature">The cryptographic RSA signature.</param> /// <returns>The hash.</returns> public static IHash ComputeRsaHashWithSignature(RSAParameters rsaParameters, bool includePrivateParameters, IEnumerable <byte> embeddedData, RsaSignature signature) { using (var stream = new MemoryStream()) { var data = new List <byte[]>(); data.Add(rsaParameters.Exponent); data.Add(rsaParameters.Modulus); if (includePrivateParameters) { data.Add(new byte[] { 0x01 }); data.Add(rsaParameters.D); data.Add(rsaParameters.DP); data.Add(rsaParameters.DQ); data.Add(rsaParameters.InverseQ); data.Add(rsaParameters.P); data.Add(rsaParameters.Q); } else { data.Add(new byte[] { 0x00 }); } if (embeddedData != null) { data.Add(new byte[] { 0x01 }); data.Add(Sha512Hash.Compute(embeddedData.ToArray()).Hash.ToArray()); } else { data.Add(new byte[] { 0x00 }); } if (signature != null) { data.Add(new byte[] { 0x01 }); data.Add(signature.Hash.Hash.ToArray()); } else { data.Add(new byte[] { 0x00 }); } int i = 0; foreach (var d in data) { var iBytes = BitConverter.GetBytes(i); if (!BitConverter.IsLittleEndian) { iBytes = iBytes.Reverse().ToArray(); } stream.Write(iBytes, 0, iBytes.Length); var info = d; if (!BitConverter.IsLittleEndian) { info = info.Reverse().ToArray(); } stream.Write(info, 0, info.Length); } stream.Position = 0; return(Sha512Hash.Compute(stream)); } }