IText 7 Unknown key algorithm: ECGOST3410

375 Views Asked by At

I'm trying to digitally sign pdf document on android (api 26) using IText 7('com.itextpdf:itext7-core:7.1.17') with the GOST3410 algorithm. BouncyCastle libraries: 'org.bouncycastle:bcprov-jdk15on:1.54' and 'org.bouncycastle:bcpkix-jdk15on:1.54' Here's my function:

fun redButton(
    pdfByteArray: ByteArray,
    certificates: Array<java.security.cert.Certificate>,
    privateKey: PrivateKey,
    contentResolver: ContentResolver,
    outUri: Uri
) {
    val provider = BouncyCastleProvider()
    Security.removeProvider(provider.name)
    Security.addProvider(provider)

    val pdfInputStream = ByteArrayInputStream(pdfByteArray)
    val reader = PdfReader(pdfInputStream)
    val outputStream = contentResolver.openOutputStream(outUri)
    val signer = PdfSigner(reader, outputStream, false)

    val appearance = signer.signatureAppearance

    appearance.reason = "study"
    appearance.setReuseAppearance(false)

    val privateKeySignature = PrivateKeySignature(
        privateKey,
        "GOST3411",
        provider.name
    )
    val bouncyCastleDigest = BouncyCastleDigest()
    signer.signDetached(
        bouncyCastleDigest,
        privateKeySignature,
        certificates,
        null,
        null,
        null,
        0,
        PdfSigner.CryptoStandard.CMS
    )
}

This code throws exception:

com.itextpdf.kernel.PdfException: Unknown key algorithm: ECGOST3410.
at com.itextpdf.signatures.PdfPKCS7.setExternalDigest(PdfPKCS7.java:695)
at com.itextpdf.signatures.PdfSigner.signDetached(PdfSigner.java:646)
at com.itextpdf.signatures.PdfSigner.signDetached(PdfSigner.java:538)
at com.example.digitalsignature.app.services.SigningTestIText.redButton(SigningTestIText.kt:38)

If this lib doesn't support GOST3410 can i write my custom byte array in signature space in pdf file?

1

There are 1 best solutions below

0
On BEST ANSWER

As mkl said custom signature container implementing IExternalSignatureContainer works well. Here's class example from PrivateKeySignatureContainerBC:

class PrivateKeySignatureContainerBC(
    signatureAlgorithm: String?,
    privateKey: PrivateKey?,
    private val x509Certificate: X509Certificate,
    private val subfilter: PdfName
) : IExternalSignatureContainer {
    override fun sign(data: InputStream): ByteArray {
        return try {
            val msg: CMSTypedData = CMSTypedDataInputStream(data)
            val signCert = X509CertificateHolder(x509Certificate.encoded)
            val gen = CMSSignedDataGenerator()
            gen.addSignerInfoGenerator(
                JcaSignerInfoGeneratorBuilder(
                    JcaDigestCalculatorProviderBuilder().setProvider("BC").build()
                )
                    .build(contentSigner, signCert)
            )
            gen.addCertificates(JcaCertStore(Collections.singleton(signCert)))
            val sigData = gen.generate(msg, false)
            sigData.encoded
        } catch (e: IOException) {
            throw GeneralSecurityException(e)
        }
    }

    override fun modifySigningDictionary(signDic: PdfDictionary) {
        signDic.put(PdfName.Filter, PdfName("MKLx_GENERIC_SIGNER"))
        signDic.put(PdfName.SubFilter, subfilter)
    }

    private val contentSigner: ContentSigner = JcaContentSignerBuilder(signatureAlgorithm).build(privateKey)

    internal inner class CMSTypedDataInputStream(var `in`: InputStream) : CMSTypedData {
        override fun getContentType(): ASN1ObjectIdentifier {
            return PKCSObjectIdentifiers.data
        }

        override fun getContent(): Any {
            return `in`
        }

        override fun write(out: OutputStream) {
            val buffer = ByteArray(8 * 1024)
            var read: Int
            while (`in`.read(buffer).also { read = it } != -1) {
                out.write(buffer, 0, read)
            }
            `in`.close()
        }
    }
}

Suggested class call by signer.signExternalContainer:

signer.signExternalContainer(
            PrivateKeySignatureContainerBC(
                "GOST3411withECGOST3410",
                privateKey,
                certificate,
                PdfName.Adbe_pkcs7_detached
            ),
            _estimatedSize
        )