Compare commits
	
		
			4 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						a5176b5bbb
	
				 | 
					
					
						|||
| 
						
						
							
						
						af6a937033
	
				 | 
					
					
						|||
| 
						
						
							
						
						8913f8ba9c
	
				 | 
					
					
						|||
| 
						
						
							
						
						524eea9b2f
	
				 | 
					
					
						
							
								
								
									
										9
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,3 +1,12 @@
 | 
				
			|||||||
 | 
					1.1.1 (2020-09-06)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Fix a dysfunctional example in the manual
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Go: write the xref table in a deterministic order
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Add a trivial test suite, based on pdfsig from poppler-utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1.1 (2020-09-05)
 | 
					1.1 (2020-09-05)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 * Make it possible to change the signature reservation with an option
 | 
					 * Make it possible to change the signature reservation with an option
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
project('pdf-simple-sign', 'cpp', default_options : ['cpp_std=c++11'],
 | 
					project('pdf-simple-sign', 'cpp', default_options : ['cpp_std=c++11'],
 | 
				
			||||||
	version : '1.1')
 | 
						version : '1.1.1')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
conf = configuration_data()
 | 
					conf = configuration_data()
 | 
				
			||||||
conf.set('PROJECT_NAME', '"' + meson.project_name() + '"')
 | 
					conf.set('PROJECT_NAME', '"' + meson.project_name() + '"')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,10 +50,11 @@ Examples
 | 
				
			|||||||
Create a self-signed certificate, make a document containing the current date,
 | 
					Create a self-signed certificate, make a document containing the current date,
 | 
				
			||||||
sign it and verify the attached signature:
 | 
					sign it and verify the attached signature:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 $ openssl req -newkey rsa:2048 -subj "/CN=Test" -nodes
 | 
					 $ openssl req -newkey rsa:2048 -subj /CN=Test -nodes \
 | 
				
			||||||
   -keyout key.pem -x509 -out cert.pem 2>/dev/null
 | 
					   -keyout key.pem -x509 -addext keyUsage=digitalSignature \
 | 
				
			||||||
 | 
					   -out cert.pem 2>/dev/null
 | 
				
			||||||
 $ openssl pkcs12 -inkey key.pem -in cert.pem \
 | 
					 $ openssl pkcs12 -inkey key.pem -in cert.pem \
 | 
				
			||||||
   -export -passout pass:test -out key-cert.p12
 | 
					   -export -passout pass: -out key-pair.p12
 | 
				
			||||||
 $ date | groff -T pdf > test.pdf
 | 
					 $ date | groff -T pdf > test.pdf
 | 
				
			||||||
 $ pdf-simple-sign test.pdf test.signed.pdf key-pair.p12 ""
 | 
					 $ pdf-simple-sign test.pdf test.signed.pdf key-pair.p12 ""
 | 
				
			||||||
 $ pdfsig test.signed.pdf
 | 
					 $ pdfsig test.signed.pdf
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								pdf/pdf.go
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								pdf/pdf.go
									
									
									
									
									
								
							@@ -853,30 +853,19 @@ func (u *Updater) FlushUpdates() {
 | 
				
			|||||||
		return updated[i] < updated[j]
 | 
							return updated[i] < updated[j]
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	groups := make(map[uint]uint)
 | 
					 | 
				
			||||||
	for i := 0; i < len(updated); {
 | 
					 | 
				
			||||||
		start, count := updated[i], uint(1)
 | 
					 | 
				
			||||||
		for i++; i != len(updated) && updated[i] == start+count; i++ {
 | 
					 | 
				
			||||||
			count++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		groups[start] = count
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Taking literally "Each cross-reference section begins with a line
 | 
					 | 
				
			||||||
	// containing the keyword xref. Following this line are one or more
 | 
					 | 
				
			||||||
	// cross-reference subsections." from 3.4.3 in PDF Reference.
 | 
					 | 
				
			||||||
	if len(groups) == 0 {
 | 
					 | 
				
			||||||
		groups[0] = 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buf := bytes.NewBuffer(u.Document)
 | 
						buf := bytes.NewBuffer(u.Document)
 | 
				
			||||||
	startXref := buf.Len() + 1
 | 
						startXref := buf.Len() + 1
 | 
				
			||||||
	buf.WriteString("\nxref\n")
 | 
						buf.WriteString("\nxref\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for start, count := range groups {
 | 
						for i := 0; i < len(updated); {
 | 
				
			||||||
		fmt.Fprintf(buf, "%d %d\n", start, count)
 | 
							start, stop := updated[i], updated[i]+1
 | 
				
			||||||
		for i := uint(0); i < count; i++ {
 | 
							for i++; i < len(updated) && updated[i] == stop; i++ {
 | 
				
			||||||
			ref := u.xref[start+uint(i)]
 | 
								stop++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fmt.Fprintf(buf, "%d %d\n", start, stop-start)
 | 
				
			||||||
 | 
							for ; start < stop; start++ {
 | 
				
			||||||
 | 
								ref := u.xref[start]
 | 
				
			||||||
			if ref.nonfree {
 | 
								if ref.nonfree {
 | 
				
			||||||
				fmt.Fprintf(buf, "%010d %05d n \n", ref.offset, ref.generation)
 | 
									fmt.Fprintf(buf, "%010d %05d n \n", ref.offset, ref.generation)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
@@ -885,6 +874,13 @@ func (u *Updater) FlushUpdates() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Taking literally "Each cross-reference section begins with a line
 | 
				
			||||||
 | 
						// containing the keyword xref. Following this line are one or more
 | 
				
			||||||
 | 
						// cross-reference subsections." from 3.4.3 in PDF Reference.
 | 
				
			||||||
 | 
						if len(updated) == 0 {
 | 
				
			||||||
 | 
							fmt.Fprintf(buf, "%d %d\n", 0, 0)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u.Trailer["Size"] = NewNumeric(float64(u.xrefSize))
 | 
						u.Trailer["Size"] = NewNumeric(float64(u.xrefSize))
 | 
				
			||||||
	trailer := NewDict(u.Trailer)
 | 
						trailer := NewDict(u.Trailer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										77
									
								
								test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										77
									
								
								test.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					#!/bin/sh -e
 | 
				
			||||||
 | 
					# Test basic functionality of both versions
 | 
				
			||||||
 | 
					# Usage: ./test.sh builddir/pdf-simple-sign cmd/pdf-simple-sign/pdf-simple-sign
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					log() { echo "`tput sitm`-- $1`tput sgr0`"; }
 | 
				
			||||||
 | 
					die() { echo "`tput bold`-- $1`tput sgr0`"; exit 1; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Get rid of old test files
 | 
				
			||||||
 | 
					rm -rf tmp
 | 
				
			||||||
 | 
					mkdir tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create documents in various tools
 | 
				
			||||||
 | 
					log "Creating source documents"
 | 
				
			||||||
 | 
					inkscape --pipe --export-filename=tmp/cairo.pdf <<'EOF' 2>/dev/null || :
 | 
				
			||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg"><text x="5" y="10">Hello</text></svg>
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					date | tee tmp/lowriter.txt | groff -T pdf > tmp/groff.pdf || :
 | 
				
			||||||
 | 
					lowriter --convert-to pdf tmp/lowriter.txt --outdir tmp >/dev/null || :
 | 
				
			||||||
 | 
					convert rose: tmp/imagemagick.pdf || :
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create a root CA certificate pair
 | 
				
			||||||
 | 
					log "Creating certificates"
 | 
				
			||||||
 | 
					openssl req -newkey rsa:2048 -subj "/CN=Test CA" -nodes \
 | 
				
			||||||
 | 
						-keyout tmp/ca.key.pem -x509 -out tmp/ca.cert.pem 2>/dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create a private NSS database and insert our test CA there
 | 
				
			||||||
 | 
					rm -rf tmp/nssdir
 | 
				
			||||||
 | 
					mkdir tmp/nssdir
 | 
				
			||||||
 | 
					certutil -N --empty-password -d sql:tmp/nssdir
 | 
				
			||||||
 | 
					certutil -d sql:tmp/nssdir -A -n root -t ,C, -a -i tmp/ca.cert.pem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create a leaf certificate pair
 | 
				
			||||||
 | 
					cat > tmp/cert.cfg <<'EOF'
 | 
				
			||||||
 | 
					[smime]
 | 
				
			||||||
 | 
					basicConstraints = CA:FALSE
 | 
				
			||||||
 | 
					keyUsage = digitalSignature
 | 
				
			||||||
 | 
					extendedKeyUsage = emailProtection
 | 
				
			||||||
 | 
					nsCertType = email
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					openssl req -newkey rsa:2048 -subj "/CN=Test Leaf" -nodes \
 | 
				
			||||||
 | 
						-keyout tmp/key.pem -out tmp/cert.csr 2>/dev/null
 | 
				
			||||||
 | 
					openssl x509 -req -in tmp/cert.csr -out tmp/cert.pem \
 | 
				
			||||||
 | 
						-CA tmp/ca.cert.pem -CAkey tmp/ca.key.pem -set_serial 1 \
 | 
				
			||||||
 | 
						-extensions smime -extfile tmp/cert.cfg 2>/dev/null
 | 
				
			||||||
 | 
					openssl verify -CAfile tmp/ca.cert.pem tmp/cert.pem >/dev/null
 | 
				
			||||||
 | 
					openssl pkcs12 -inkey tmp/key.pem -in tmp/cert.pem \
 | 
				
			||||||
 | 
						-export -passout pass: -out tmp/key-pair.p12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for tool in "$@"; do
 | 
				
			||||||
 | 
						rm -f tmp/*.signed.pdf
 | 
				
			||||||
 | 
						for source in tmp/*.pdf; do
 | 
				
			||||||
 | 
							log "Testing $tool with $source"
 | 
				
			||||||
 | 
							result=${source%.pdf}.signed.pdf
 | 
				
			||||||
 | 
							$tool "$source" "$result" tmp/key-pair.p12 ""
 | 
				
			||||||
 | 
							pdfsig -nssdir sql:tmp/nssdir "$result" | grep Validation
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log "Testing $tool for expected failures"
 | 
				
			||||||
 | 
						$tool "$result" "$source.fail.pdf" tmp/key-pair.p12 "" \
 | 
				
			||||||
 | 
							&& die "Double signing shouldn't succeed"
 | 
				
			||||||
 | 
						$tool -r 1 "$source" "$source.fail.pdf" tmp/key-pair.p12 "" \
 | 
				
			||||||
 | 
							&& die "Too low reservations shouldn't succeed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Our generators do not use PDF versions higher than 1.5
 | 
				
			||||||
 | 
						log "Testing $tool for version detection"
 | 
				
			||||||
 | 
						grep -q "/Version /1.6" "$result" \
 | 
				
			||||||
 | 
							|| die "Version detection seems to misbehave (no upgrade)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sed '1s/%PDF-1../%PDF-1.7/' "$source" > "$source.alt"
 | 
				
			||||||
 | 
						$tool "$source.alt" "$result.alt" tmp/key-pair.p12 ""
 | 
				
			||||||
 | 
						grep -q "/Version /1.6" "$result.alt" \
 | 
				
			||||||
 | 
							&& die "Version detection seems to misbehave (downgraded)"
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					log "OK"
 | 
				
			||||||
		Reference in New Issue
	
	Block a user