/// <inheritdoc /> public byte[] ComputeHash(string contentToSign) { var inputBytes = Encoding.UTF8.GetBytes(contentToSign); HashAlgorithm hasher = null; try { hasher = _hasherPool.Get(); var hashedData = hasher.ComputeHash(inputBytes); return(_ecdsa.SignHash(hashedData)); } finally { if (hasher != null) { _hasherPool.Return(hasher); } } }
public void SignVerify_InteroperableSameKeys_RoundTripsUnlessTampered(ECDsa ecdsa, HashAlgorithmName hashAlgorithm) { // large enough to make hashing work though multiple iterations and not a multiple of 4KB it uses. byte[] dataArray = new byte[33333]; byte[] dataArray2 = new byte[dataArray.Length + 2]; dataArray.CopyTo(dataArray2, 1); using HashAlgorithm halg = hashAlgorithm == HashAlgorithmName.MD5 ? MD5.Create() : hashAlgorithm == HashAlgorithmName.SHA1 ? SHA1.Create() : hashAlgorithm == HashAlgorithmName.SHA256 ? SHA256.Create() : hashAlgorithm == HashAlgorithmName.SHA384 ? SHA384.Create() : hashAlgorithm == HashAlgorithmName.SHA512 ? SHA512.Create() : throw new Exception("Hash algorithm not supported."); List <byte[]> signatures = new List <byte[]>(6); // Compute a signature using each of the SignData overloads. Then, verify it using each // of the VerifyData overloads, and VerifyHash overloads. // // Then, verify that VerifyHash fails if the data is tampered with. signatures.Add(SignData(ecdsa, dataArray, hashAlgorithm)); signatures.Add(ecdsa.SignHash(halg.ComputeHash(dataArray))); foreach (byte[] signature in signatures) { Assert.True(VerifyData(ecdsa, dataArray, signature, hashAlgorithm), "Verify 1"); Assert.True(ecdsa.VerifyHash(halg.ComputeHash(dataArray), signature), "Verify 4"); } int distinctSignatures = signatures.Distinct(new ByteArrayComparer()).Count(); Assert.True(distinctSignatures == signatures.Count, "Signing should be randomized"); foreach (byte[] signature in signatures) { signature[signature.Length - 1] ^= 0xFF; // flip some bits Assert.False(VerifyData(ecdsa, dataArray, signature, hashAlgorithm), "Verify Tampered 1"); Assert.False(ecdsa.VerifyHash(halg.ComputeHash(dataArray), signature), "Verify Tampered 4"); } }
public override byte[] CreateSignature(byte[] rgbHash) { if (rgbHash == null) { throw new ArgumentNullException("rgbHash"); } if (m_key == null) { throw new Exception("Must initialize key before creating a signature"); } if (m_hashAlgorithm == null) { throw new Exception("Must initialize hash algorithm before creating a signature"); } byte[] signature = m_key.SignHash(rgbHash); return(signature); }
public static byte[] ECDsaSignHash(BigInteger privateKey, byte[] hash) { if (!IsPrivateKeyValid(privateKey)) { throw new Exception("privateKey is invalid."); } ECDsa ecdsa = ECDsa.Create(ECCurve.CreateFromFriendlyName("secp256k1")); // windows 10: https://docs.microsoft.com/en-us/windows/desktop/SecCNG/cng-named-elliptic-curves ECParameters parameters = ecdsa.ExportExplicitParameters(true); parameters.D = Encode.BigIntegerToBytes(privateKey, 32); // parameters.Q is not used in SignHash ecdsa.ImportParameters(parameters); while (true) { byte[] sig = ecdsa.SignHash(hash); // 64 bytes if (sig[32] < 0x7f) // low s value { return(sig); } } }
public void SignVerify_InteroperableSameKeys_RoundTripsUnlessTampered(ECDsa ecdsa, HashAlgorithmName hashAlgorithm) { byte[] data = Encoding.UTF8.GetBytes("something to repeat and sign"); // large enough to make hashing work though multiple iterations and not a multiple of 4KB it uses. byte[] dataArray = new byte[33333]; MemoryStream dataStream = new MemoryStream(dataArray, true); while (dataStream.Position < dataArray.Length - data.Length) { dataStream.Write(data, 0, data.Length); } dataStream.Position = 0; byte[] dataArray2 = new byte[dataArray.Length + 2]; dataArray.CopyTo(dataArray2, 1); ArraySegment <byte> dataSpan = new ArraySegment <byte>(dataArray2, 1, dataArray.Length); HashAlgorithm halg; if (hashAlgorithm == HashAlgorithmName.MD5) { halg = MD5.Create(); } else if (hashAlgorithm == HashAlgorithmName.SHA1) { halg = SHA1.Create(); } else if (hashAlgorithm == HashAlgorithmName.SHA256) { halg = SHA256.Create(); } else if (hashAlgorithm == HashAlgorithmName.SHA384) { halg = SHA384.Create(); } else if (hashAlgorithm == HashAlgorithmName.SHA512) { halg = SHA512.Create(); } else { throw new Exception("Hash algorithm not supported."); } List <byte[]> signatures = new List <byte[]>(6); // Compute a signature using each of the SignData overloads. Then, verify it using each // of the VerifyData overloads, and VerifyHash overloads. // // Then, verify that VerifyHash fails if the data is tampered with. signatures.Add(ecdsa.SignData(dataArray, hashAlgorithm)); signatures.Add(ecdsa.SignData(dataSpan.Array, dataSpan.Offset, dataSpan.Count, hashAlgorithm)); signatures.Add(ecdsa.SignData(dataStream, hashAlgorithm)); dataStream.Position = 0; signatures.Add(ecdsa.SignHash(halg.ComputeHash(dataArray))); signatures.Add(ecdsa.SignHash(halg.ComputeHash(dataSpan.Array, dataSpan.Offset, dataSpan.Count))); signatures.Add(ecdsa.SignHash(halg.ComputeHash(dataStream))); dataStream.Position = 0; foreach (byte[] signature in signatures) { Assert.True(ecdsa.VerifyData(dataArray, signature, hashAlgorithm), "Verify 1"); Assert.True(ecdsa.VerifyData(dataSpan.Array, dataSpan.Offset, dataSpan.Count, signature, hashAlgorithm), "Verify 2"); Assert.True(ecdsa.VerifyData(dataStream, signature, hashAlgorithm), "Verify 3"); Assert.True(dataStream.Position == dataArray.Length, "Check stream read 3A"); dataStream.Position = 0; Assert.True(ecdsa.VerifyHash(halg.ComputeHash(dataArray), signature), "Verify 4"); Assert.True(ecdsa.VerifyHash(halg.ComputeHash(dataSpan.Array, dataSpan.Offset, dataSpan.Count), signature), "Verify 5"); Assert.True(ecdsa.VerifyHash(halg.ComputeHash(dataStream), signature), "Verify 6"); Assert.True(dataStream.Position == dataArray.Length, "Check stream read 6A"); dataStream.Position = 0; } int distinctSignatures = signatures.Distinct(new ByteArrayComparer()).Count(); Assert.True(distinctSignatures == signatures.Count, "Signing should be randomized"); foreach (byte[] signature in signatures) { signature[signature.Length - 1] ^= 0xFF; // flip some bits Assert.False(ecdsa.VerifyData(dataArray, signature, hashAlgorithm), "Verify Tampered 1"); Assert.False(ecdsa.VerifyData(dataSpan.Array, dataSpan.Offset, dataSpan.Count, signature, hashAlgorithm), "Verify Tampered 2"); Assert.False(ecdsa.VerifyData(dataStream, signature, hashAlgorithm), "Verify Tampered 3"); Assert.True(dataStream.Position == dataArray.Length, "Check stream read 3B"); dataStream.Position = 0; Assert.False(ecdsa.VerifyHash(halg.ComputeHash(dataArray), signature), "Verify Tampered 4"); Assert.False(ecdsa.VerifyHash(halg.ComputeHash(dataSpan.Array, dataSpan.Offset, dataSpan.Count), signature), "Verify Tampered 5"); Assert.False(ecdsa.VerifyHash(halg.ComputeHash(dataStream), signature), "Verify Tampered 6"); Assert.True(dataStream.Position == dataArray.Length, "Check stream read 6B"); dataStream.Position = 0; } }
public void SignHash_NullHash_ThrowsArgumentNullException(ECDsa ecdsa) { AssertExtensions.Throws <ArgumentNullException>( "hash", () => ecdsa.SignHash(null)); }
private byte[] SignWithECDsa(byte[] bytes) { return(ECDsa.SignHash(HashAlgorithm.ComputeHash(bytes))); }
protected override byte[] SignHash(ECDsa ecdsa, byte[] hash, int offset, int count) => ecdsa.SignHash(new ReadOnlySpan <byte>(hash, offset, count));
protected override byte[] SignHash(ECDsa ecdsa, byte[] hash, int offset, int count) => WithOutputArray(dest => ecdsa.SignHash(new ReadOnlySpan <byte>(hash, offset, count), dest));
public byte[] Sign(byte[] digest) { return(_key.SignHash(digest)); }
public byte[] Sign(byte[] hash) { return(_signer.SignHash(hash)); }
//ECDSA doesn't have the PKCS#1 / PSS hashing problem, so the hash is thrown away. public byte[] SignDigest(byte[] digest, HashAlgorithmName pkcsAlgorithm) => _algorithm.SignHash(digest);
private static void RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) { string key = args.Request.Message.First().Key; string value = args.Request.Message.First().Value.ToString(); JsonObject request = JsonValue.Parse(value).GetObject(); JsonObject response = new JsonObject { { "api", JsonValue.CreateNumberValue(1) }, { "result", JsonValue.CreateStringValue("ok") } }; if (request.ContainsKey("nonce")) { response.Add("nonce", request.GetNamedValue("nonce")); } switch (request.GetNamedString("type")) { case "VERSION": PackageVersion version = Package.Current.Id.Version; response.Add("version", JsonValue.CreateStringValue( string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision))); args.Request.SendResponseAsync(new ValueSet { ["message"] = response.ToString() }).Completed += delegate { }; break; case "CERT": try { String info = "By selecting a certificate I accept that my name and personal ID code will be sent to service provider."; switch (request.GetNamedString("lang").ToString()) { case "et": case "est": info = "Sertifikaadi valikuga nõustun oma nime ja isikukoodi edastamisega teenusepakkujale."; break; case "lt": case "lit": info = "Pasirinkdama(s) sertifikatą, aš sutinku, kad mano vardas, pavardė ir asmens kodas būtų perduoti e. paslaugos teikėjui."; break; case "lv": case "lat": info = "Izvēloties sertifikātu, es apstiprinu, ka mans vārds un personas kods tiks nosūtīts pakalpojuma sniedzējam."; break; case "ru": case "rus": info = "Выбирая сертификат, я соглащаюсь с тем, что мое имя и личный код будут переданы представителю услуг."; break; default: break; } X509Certificate2Collection list = new X509Certificate2Collection(); using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) { store.Open(OpenFlags.ReadOnly); bool forSigning = request.GetNamedString("filter", "SIGN").ToString() != "AUTH"; foreach (X509Certificate2 x in store.Certificates.Find(X509FindType.FindByTimeValid, DateTime.Now, false)) { List <X509KeyUsageExtension> extensions = x.Extensions.OfType <X509KeyUsageExtension>().ToList(); if (extensions.Any() && ((extensions[0].KeyUsages & X509KeyUsageFlags.NonRepudiation) > 0) == forSigning && HasHWToken(x)) { list.Add(x); } } } if (list.Count > 0) { X509Certificate2Collection certs = X509Certificate2UI.SelectFromCollection( list, "", info, X509SelectionFlag.SingleSelection); if (certs.Count > 0) { response.Add("cert", JsonValue.CreateStringValue(ByteToString(certs[0].Export(X509ContentType.Cert), false))); } else { response["result"] = JsonValue.CreateStringValue("user_cancel"); response.Add("message", JsonValue.CreateStringValue("user_cancel")); } } else { response["result"] = JsonValue.CreateStringValue("no_certificates"); response.Add("message", JsonValue.CreateStringValue("no_certificates")); } } catch (Exception e) { response["result"] = JsonValue.CreateStringValue("technical_error"); response.Add("message", JsonValue.CreateStringValue(e.Message)); } args.Request.SendResponseAsync(new ValueSet { ["message"] = response.ToString() }).Completed += delegate { }; break; case "SIGN": try { String info = request.GetNamedString("info", ""); if (info.Length > 500) { throw new ArgumentException("Info parameter longer than 500 chars"); } if (info.Length > 0 && MessageBox.Show(info, "", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.No) { throw new Exception("User cancelled"); } X509Certificate2 cert = new X509Certificate2(StringToByte(request.GetNamedString("cert"))); if (cert == null) { throw new ArgumentException("Failed to parse certificate"); } X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false); if (certs.Count == 0) { throw new ArgumentException("Failed to find certificate"); } byte[] signature = null; if (certs[0].PublicKey.Oid.Value.Equals("1.2.840.10045.2.1")) { using (ECDsa ecdsa = certs[0].GetECDsaPrivateKey()) { if (ecdsa == null) { throw new ArgumentException("Failed to find certificate token"); } signature = ecdsa.SignHash(StringToByte(request.GetNamedString("hash"))); } } else { using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certs[0].PrivateKey) { if (rsa == null) { throw new ArgumentException("Failed to find certificate token"); } signature = rsa.SignHash(StringToByte(request.GetNamedString("hash")), CryptoConfig.MapNameToOID(request.GetNamedString("hashtype").Replace("-", ""))); } } if (signature == null) { throw new Exception("Failed to sign hash"); } response.Add("signature", JsonValue.CreateStringValue(ByteToString(signature, false))); } catch (Exception e) { if (e is ArgumentException || e is ArgumentNullException) { response["result"] = JsonValue.CreateStringValue("invalid_argument"); } else if (e.Message.Contains("cancelled")) { response["result"] = JsonValue.CreateStringValue("user_cancel"); } else { response["result"] = JsonValue.CreateStringValue("technical_error"); } response.Add("message", JsonValue.CreateStringValue(e.Message)); } args.Request.SendResponseAsync(new ValueSet { ["message"] = response.ToString() }).Completed += delegate { }; break; default: Application.Exit(); break; } }
public override byte[] SignHash(byte[] hash) => _impl.SignHash(hash);
protected static byte[] SignData(ECDsa key, params byte[][] data) { byte[] hash = HashData(HashAlgorithmName.SHA256, data); return(key.SignHash(hash)); }