Как реализовать мою собственную функцию для проверки подписи SM2? - PullRequest
0 голосов
/ 17 января 2019

В своей работе я должен использовать китайский алгоритм шифрования SM2, чтобы подписать pdf и проверить подпись, и я выбрал itext, чтобы помочь моей работе. Но поскольку я впервые использую itext lib, я так незнаком с это.

Часть подписи Я использовал внешнюю подпись, помещая подпись SM2 в словарь подписи PDF. Я могу найти много кода в Интернете по этому поводу. Но когда дело доходит до проверки подписи, я могу найти небольшую помощь (itext не поддерживает алгоритм SM2, поэтому я не могу использовать стандартный метод Verify и должен реализовать свою собственную функцию для проверки подписи SM2). Я имею в виду, что не знаю, как получить подписанные данные о происхождении, как я делаю в часть подписи с использованием «GetRangeStream», и я не знаю, как прочитать подпись SM2 из поля формы PDF.

Кто-нибудь может мне помочь? Большое спасибо.

1 Ответ

0 голосов
/ 21 февраля 2019

Код, который вам нужен, очевидно, аналогичен коду, который метод iText AcroFields.VerifySignature выполняет при создании объекта PdfPKCS7, представляющего данную подпись. Так как iText является открытым исходным кодом, вы можете просто скопировать этот код так, как вам нужно!

* 1005 Е.Г. *

Я не знаю, как прочитать подпись SM2 из поля формы PDF.

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();
    }
}
...