Skip to content

Commit

Permalink
Use UTF-16BE encoding when required
Browse files Browse the repository at this point in the history
Fix #2
  • Loading branch information
vanbroup committed Mar 10, 2023
1 parent 7fd1d3d commit 4fb6faf
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 8 deletions.
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ go 1.17

require (
github.com/digitorus/pdf v0.1.2
github.com/digitorus/pkcs7 v0.0.0-20221212123742-001c36b64ec3
github.com/digitorus/timestamp v0.0.0-20221118121739-0faba6f30e54
github.com/digitorus/pkcs7 v0.0.0-20230220124406-51331ccfc40f
github.com/digitorus/timestamp v0.0.0-20230220124323-d542479a2425
github.com/mattetti/filebuffer v1.0.1
golang.org/x/crypto v0.7.0
golang.org/x/text v0.8.0
)
9 changes: 5 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
github.com/digitorus/pdf v0.1.2 h1:RjYEJNbiV6Kcn8QzRi6pwHuOaSieUUrg4EZo4b7KuIQ=
github.com/digitorus/pdf v0.1.2/go.mod h1:05fDDJhPswBRM7GTfqCxNiDyeNcN0f+IobfOAl5pdXw=
github.com/digitorus/pkcs7 v0.0.0-20221019075359-21b8b40e6bb4/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc=
github.com/digitorus/pkcs7 v0.0.0-20221212123742-001c36b64ec3 h1:rjCXeRWazGsbcBlExMcAW8H1LGdgJ9r619y7+aeKgds=
github.com/digitorus/pkcs7 v0.0.0-20221212123742-001c36b64ec3/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc=
github.com/digitorus/timestamp v0.0.0-20221118121739-0faba6f30e54 h1:VPfvrlgI2O3mQjBBLywtPxjDMlpWYWobXN3nk26Ht0k=
github.com/digitorus/timestamp v0.0.0-20221118121739-0faba6f30e54/go.mod h1:6V2ND8Yf8TOJ4h+9pmUlx8kXvNLBB2QplToVVZQ3rF0=
github.com/digitorus/pkcs7 v0.0.0-20230220124406-51331ccfc40f h1:AoHV/iJ6LjW24bRWrg0zm1xD3Uh83PlNSK0QWH11J0E=
github.com/digitorus/pkcs7 v0.0.0-20230220124406-51331ccfc40f/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc=
github.com/digitorus/timestamp v0.0.0-20230220124323-d542479a2425 h1:cbnavmdMqZ3b4hcCxizSO/jO+BxyXp/hU9jyzULJ9g8=
github.com/digitorus/timestamp v0.0.0-20230220124323-d542479a2425/go.mod h1:6V2ND8Yf8TOJ4h+9pmUlx8kXvNLBB2QplToVVZQ3rF0=
github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM=
github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand Down Expand Up @@ -37,6 +37,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
Expand Down
31 changes: 30 additions & 1 deletion sign/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
"time"

"github.com/digitorus/pdf"

"golang.org/x/text/encoding/unicode"
"golang.org/x/text/transform"
)

func findFirstPage(parent pdf.Value) (pdf.Value, error) {
Expand All @@ -35,11 +38,28 @@ func findFirstPage(parent pdf.Value) (pdf.Value, error) {
}

func pdfString(text string) string {
if !isASCII(text) {
// UTF-16BE
enc := unicode.UTF16(unicode.BigEndian, unicode.UseBOM).NewEncoder()
res, _, err := transform.String(enc, text)
if err != nil {
panic(err)
}
return "(" + res + ")"
}

// UTF-8
// (\357\273\277Layer 1) % UTF-8 Layer 1 Name
// <EF BB BF DA AF DA 86 D9 BE DA 98> % UTF-8 Layer 2 Name
// text = "\357\273\277" + text
// text = hex.EncodeToString([]byte(text))
// text = "<" + text + ">"

// PDFDocEncoded
text = strings.Replace(text, "\\", "\\\\", -1)
text = strings.Replace(text, ")", "\\)", -1)
text = strings.Replace(text, "(", "\\(", -1)
text = strings.Replace(text, "\r", "\\r", -1)

text = "(" + text + ")"

return text
Expand Down Expand Up @@ -167,3 +187,12 @@ func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
}
return nil
}

func isASCII(s string) bool {
for _, r := range s {
if r > '\u007F' {
return false
}
}
return true
}
78 changes: 77 additions & 1 deletion sign/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func TestReaderCanReadPDF(t *testing.T) {
if ext != ".pdf" {
continue
}

fileName := f.Name()
t.Run(fileName, func(st *testing.T) {
st.Parallel()
Expand Down Expand Up @@ -285,6 +285,82 @@ func TestSignPDFFile(t *testing.T) {
}
}

func TestSignPDFFileUTF8(t *testing.T) {
certificate_data_block, _ := pem.Decode([]byte(signCertPem))
if certificate_data_block == nil {
t.Errorf("failed to parse PEM block containing the certificate")
return
}

cert, err := x509.ParseCertificate(certificate_data_block.Bytes)
if err != nil {
t.Errorf("%s", err.Error())
return
}

key_data_block, _ := pem.Decode([]byte(signKeyPem))
if key_data_block == nil {
t.Errorf("failed to parse PEM block containing the private key")
return
}

pkey, err := x509.ParsePKCS1PrivateKey(key_data_block.Bytes)
if err != nil {
t.Errorf("%s", err.Error())
return
}

tmpfile, err := os.CreateTemp("", "pdfsign_test")
if err != nil {
t.Errorf("%s", err.Error())
return
}

signerName := "姓名"
signerLocation := "位置"
err = SignFile("../testfiles/testfile20.pdf", tmpfile.Name(), SignData{
Signature: SignDataSignature{
Info: SignDataSignatureInfo{
Name: signerName,
Location: signerLocation,
Reason: "Test with UTF-8",
ContactInfo: "None",
Date: time.Now().Local(),
},
CertType: CertificationSignature,
DocMDPPerm: AllowFillingExistingFormFieldsAndSignaturesPerms,
},
DigestAlgorithm: crypto.SHA512,
Signer: pkey,
Certificate: cert,
})

if err != nil {
os.Remove(tmpfile.Name())
t.Errorf("%s: %s", "testfile20.pdf", err.Error())
return
}

info, err := verify.File(tmpfile)
if err != nil {
t.Errorf("%s: %s", tmpfile.Name(), err.Error())

err2 := os.Rename(tmpfile.Name(), "../testfiles/failed/testfile20.pdf")
if err2 != nil {
t.Error(err2)
}
} else {
if info.Signers[0].Name != signerName {
t.Errorf("expected %q, got %q", signerName, info.Signers[0].Name)
}
if info.Signers[0].Location != signerLocation {
t.Errorf("expected %q, got %q", signerLocation, info.Signers[0].Location)
}

os.Remove(tmpfile.Name())
}
}

func BenchmarkSignPDF(b *testing.B) {
certificate_data_block, _ := pem.Decode([]byte(signCertPem))
if certificate_data_block == nil {
Expand Down

0 comments on commit 4fb6faf

Please sign in to comment.