Compare commits
	
		
			4 Commits
		
	
	
		
			3ce08d33f6
			...
			a5176b5bbb
		
	
	| 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" | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user