gpt4 book ai didi

digital-signature - 验证 RFC 3161 可信时间戳

转载 作者:行者123 更新时间:2023-12-03 20:01:13 26 4
gpt4 key购买 nike

在我的构建过程中,我想包含来自符合 RFC-3161 的 TSA 的时间戳。在运行时,代码将验证这个时间戳,最好不需要第三方库的帮助。 (这是一个 .NET 应用程序,因此我可以随时使用标准哈希和非对称加密功能。)

RFC 3161,它依赖于 ASN.1 和 X.690 等等,实现起来并不简单,所以至少现在,我使用 Bouncy CaSTLe 来生成 TimeStampReq(请求)并解析 TimeStampResp(响应)。我只是无法弄清楚如何验证响应。

到目前为止,我已经弄清楚了如何提取签名本身、公共(public)证书、创建时间戳的时间以及我发送的消息印记摘要和随机数(用于构建时验证)。我不知道如何将这些数据放在一起以生成经过散列和签名的数据。

这是我正在做什么以及我正在尝试做什么的粗略想法。这是测试代码,所以我采取了一些捷径。一旦我得到一些有用的东西,我将不得不清理一些东西并以正确的方式做它们。

构建时生成时间戳:

// a lot of fully-qualified type names here to make sure it's clear what I'm using

static void WriteTimestampToBuild(){
var dataToTimestamp = Encoding.UTF8.GetBytes("The rain in Spain falls mainly on the plain");
var hashToTimestamp = new System.Security.Cryptography.SHA1Cng().ComputeHash(dataToTimestamp);
var nonce = GetRandomNonce();
var tsr = GetTimestamp(hashToTimestamp, nonce, "http://some.rfc3161-compliant.server");

var tst = tsr.TimeStampToken;
var tsi = tst.TimeStampInfo;

ValidateNonceAndHash(tsi, hashToTimestamp, nonce);

var cms = tst.ToCmsSignedData();

var signer =
cms.GetSignerInfos().GetSigners()
.Cast<Org.BouncyCastle.Cms.SignerInformation>().First();
// TODO: handle multiple signers?

var signature = signer.GetSignature();

var cert =
tst.GetCertificates("Collection").GetMatches(signer.SignerID)
.Cast<Org.BouncyCastle.X509.X509Certificate>().First();
// TODO: handle multiple certs (for one or multiple signers)?

ValidateCert(cert);

var timeString = tsi.TstInfo.GenTime.TimeString;
var time = tsi.GenTime; // not sure which is more useful
// TODO: Do I care about tsi.TstInfo.Accuracy or tsi.GenTimeAccuracy?

var serialNumber = tsi.SerialNumber.ToByteArray(); // do I care?

WriteToBuild(cert.GetEncoded(), signature, timeString/*or time*/, serialNumber);
// TODO: Do I need to store any more values?
}

static Org.BouncyCastle.Math.BigInteger GetRandomNonce(){
var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
var bytes = new byte[10]; // TODO: make it a random length within a range
rng.GetBytes(bytes);
return new Org.BouncyCastle.Math.BigInteger(bytes);
}

static Org.BouncyCastle.Tsp.TimeStampResponse GetTimestamp(byte[] hash, Org.BouncyCastle.Math.BigInteger nonce, string url){
var reqgen = new Org.BouncyCastle.Tsp.TimeStampRequestGenerator();
reqgen.SetCertReq(true);
var tsrequest = reqgen.Generate(Org.BouncyCastle.Tsp.TspAlgorithms.Sha1, hash, nonce);
var data = tsrequest.GetEncoded();

var webreq = WebRequest.CreateHttp(url);
webreq.Method = "POST";
webreq.ContentType = "application/timestamp-query";
webreq.ContentLength = data.Length;
using(var reqStream = webreq.GetRequestStream())
reqStream.Write(data, 0, data.Length);
using(var respStream = webreq.GetResponse().GetResponseStream())
return new Org.BouncyCastle.Tsp.TimeStampResponse(respStream);
}

static void ValidateNonceAndHash(Org.BouncyCastle.Tsp.TimeStampTokenInfo tsi, byte[] hashToTimestamp, Org.BouncyCastle.Math.BigInteger nonce){
if(tsi.Nonce != nonce)
throw new Exception("Nonce doesn't match. Man-in-the-middle attack?");

var messageImprintDigest = tsi.GetMessageImprintDigest();

var hashMismatch =
messageImprintDigest.Length != hashToTimestamp.Length ||
Enumerable.Range(0, messageImprintDigest.Length).Any(i=>
messageImprintDigest[i] != hashToTimestamp[i]
);

if(hashMismatch)
throw new Exception("Message imprint doesn't match. Man-in-the-middle attack?");
}

static void ValidateCert(Org.BouncyCastle.X509.X509Certificate cert){
// not shown, but basic X509Chain validation; throw exception on failure
// TODO: Validate certificate subject and policy
}

static void WriteToBuild(byte[] cert, byte[] signature, string time/*or DateTime time*/, byte[] serialNumber){
// not shown
}

运行时的时间戳验证(客户端站点):

// a lot of fully-qualified type names here to make sure it's clear what I'm using

static void VerifyTimestamp(){
var timestampedData = Encoding.UTF8.GetBytes("The rain in Spain falls mainly on the plain");
var timestampedHash = new System.Security.Cryptography.SHA1Cng().ComputeHash(timestampedData);

byte[] certContents;
byte[] signature;
string time; // or DateTime time
byte[] serialNumber;

GetDataStoredDuringBuild(out certContents, out signature, out time, out serialNumber);

var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certContents);

ValidateCert(cert);

var signedData = MagicallyCombineThisStuff(timestampedHash, time, serialNumber);
// TODO: What other stuff do I need to magically combine?

VerifySignature(signedData, signature, cert);

// not shown: Use time from timestamp to validate cert for other signed data
}

static void GetDataStoredDuringBuild(out byte[] certContents, out byte[] signature, out string/*or DateTime*/ time, out byte[] serialNumber){
// not shown
}

static void ValidateCert(System.Security.Cryptography.X509Certificates.X509Certificate2 cert){
// not shown, but basic X509Chain validation; throw exception on failure
}

static byte[] MagicallyCombineThisStuff(byte[] timestampedhash, string/*or DateTime*/ time, byte[] serialNumber){
// HELP!
}

static void VerifySignature(byte[] signedData, byte[] signature, System.Security.Cryptography.X509Certificates.X509Certificate2 cert){
var key = (RSACryptoServiceProvider)cert.PublicKey.Key;
// TODO: Handle DSA keys, too
var okay = key.VerifyData(signedData, CryptoConfig.MapNameToOID("SHA1"), signature);
// TODO: Make sure to use the same hash algorithm as the TSA
if(!okay)
throw new Exception("Timestamp doesn't match! Don't trust this!");
}

正如您可能猜到的那样,我认为我被卡住的地方是 MagicallyCombineThisStuff功能。

最佳答案

恭喜你完成了那个棘手的协议(protocol)工作!
另请参阅 rfc3161ng 2.0.4 上的 Python 客户端实现。 .
请注意,使用 RFC 3161 TSP 协议(protocol),如 Web Science and Digital Libraries Research Group: 2017-04-20: Trusted Timestamping of Mementos 中所述和其他出版物,您和您的依赖方必须相信时间戳管理局 (TSA) 的操作正确且安全。当然,要真正保护大多数 TSA 运行的在线服务器,即使不是不可能,也是非常困难的。
正如该论文中所讨论的那样,通过与 TSP 的比较,现在世界上有各种各样的公共(public)区 block 链,其中信任分布和(有时)仔细监控,有新的可信时间戳选项(为文档提供“存在证明”) .例如见
OriginStamp - Trusted Timestamping with Bitcoin .该协议(protocol)要简单得多,并且它们为多种语言提供客户端代码。虽然他们的在线服务器也可能受到威胁,但客户端可以检查他们的哈希是否正确嵌入到比特币区 block 链中,从而绕过信任 OriginStamp 服务本身的需要。
一个缺点是时间戳每天只发布一次,除非支付额外费用。比特币交易变得相当昂贵,因此该服务正在考虑支持其他区 block 链,以降低成本并降低获得更及时发布的成本。
更新 :查看 Stellar 和 Keybase
如需免费、高效、闪电般快速且经过广泛审查的时间戳,请查看 Stellar 区 block 链协议(protocol)和 STELLARAPI.IO服务。

关于digital-signature - 验证 RFC 3161 可信时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19528456/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com