【问题标题】:How to implement my own function to verify a SM2 signature?如何实现我自己的功能来验证 SM2 签名?
【发布时间】:2019-01-17 01:36:49
【问题描述】:

在我的工作中,我必须使用中文SM2加密算法来签署pdf并验证签名,我选择了itext来帮助我的工作。但是我是第一次使用itext lib,所以我很陌生它。

签名部分我使用外部签名,将SM2签名放入pdf的签名字典中。我可以在网上找到很多关于这个的代码。但是在验证签名时,我找不到任何帮助(itext不支持 SM2 算法,这就是为什么我不能使用标准的验证方法,必须实现我自己的函数来验证 SM2 签名)。我的意思是我不知道如何获取签名的原始数据,就像我在使用“GetRangeStream”的签名部分,我不知道如何从pdf的表单字段中读取SM2签名。

谁能帮帮我?非常感谢。

【问题讨论】:

  • 我使用 itextsharp 5.5.8
  • 如果有空行来分隔文本,则更容易阅读。

标签: c# pdf itext digital-signature


【解决方案1】:

您需要的代码显然类似于 iText 方法 AcroFields.VerifySignature 在创建代表相关签名的 PdfPKCS7 对象时执行的代码。由于 iText 是开源的,您可以根据需要简单地复制该代码!

例如

我不知道如何从 pdf 的表单域中读取 SM2 签名。

AcroFields.VerifySignature 开头是这样的:

    virtual public PdfPKCS7 VerifySignature(String name) {
        PdfDictionary v = GetSignatureDictionary(name);
        if (v == null)
            return null;
        PdfName sub = v.GetAsName(PdfName.SUBFILTER);
        PdfString contents = v.GetAsString(PdfName.CONTENTS);
        PdfPKCS7 pk = null;
        if (sub.Equals(PdfName.ADBE_X509_RSA_SHA1)) {
            PdfString cert = v.GetAsString(PdfName.CERT);
            if (cert == null)
                cert = v.GetAsArray(PdfName.CERT).GetAsString(0);
            pk = new PdfPKCS7(contents.GetOriginalBytes(), cert.GetBytes());
        }
        else
            pk = new PdfPKCS7(contents.GetOriginalBytes(), sub);

因此,提取嵌入签名对象的基本代码是这样的

AcroFields acroFields = reader.AcroFields;
PdfDictionary v = acroFields.GetSignatureDictionary(name);
if (v != null) {
    PdfString contents = v.GetAsString(PdfName.CONTENTS);
    byte[] embeddedSignatureObjectBytes = contents.GetOriginalBytes();
    [... process embeddedSignatureObjectBytes ...]
}

注意:由于 Contents 字符串用零填充,实际签名对象之后的 embeddedSignatureObjectBytes 字节将包含 0x00 字节的尾部。

我不知道如何获取签名的原始数据

AcroFields.VerifySignature 继续这样:

UpdateByteRange(pk, v);

AcroFields.UpdateByteRange 是这样实现的:

private void UpdateByteRange(PdfPKCS7 pkcs7, PdfDictionary v) {
    PdfArray b = v.GetAsArray(PdfName.BYTERANGE);
    RandomAccessFileOrArray rf = reader.SafeFile;
    Stream rg = null;
    try {
        rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(rf.CreateSourceView(), b.AsLongArray()));
        byte[] buf = new byte[8192];
        int rd;
        while ((rd = rg.Read(buf, 0, buf.Length)) > 0) {
            pkcs7.Update(buf, 0, rd);
        }
    } finally {
        if (rg != null) rg.Close();
    }
}

因此,读取签名文档字节的基本代码是这样的

AcroFields acroFields = reader.AcroFields;
PdfDictionary v = acroFields.GetSignatureDictionary(name);
if (v != null) {
    PdfArray b = v.GetAsArray(PdfName.BYTERANGE);
    RandomAccessFileOrArray rf = reader.SafeFile;
    Stream rg = null;
    try {
        rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(rf.CreateSourceView(), b.AsLongArray()));
        [... process the signed data in the Stream rg ...]
    } finally {
        if (rg != null) rg.Close();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    • 2016-12-29
    • 2017-09-08
    • 1970-01-01
    • 2012-02-29
    相关资源
    最近更新 更多