[Python-modules-commits] [python-odf] 53/118: First work on signatures. opendocument.save() will now remove signatures that was loaded

Wolfgang Borgert debacle at moszumanska.debian.org
Fri Oct 3 21:27:22 UTC 2014


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to reference refs/remotes/upstream/master
in repository python-odf.

commit 6359ddfdeb41c0ec3463eb96120edafb56a555de
Author: Søren Roug <soren.roug at eea.europa.eu>
Date:   Mon Mar 16 21:00:41 2009 +0000

    First work on signatures.
    opendocument.save() will now remove signatures that was loaded
---
 contrib/odfsign/Makefile                    |  14 ++
 contrib/odfsign/odfsign                     |  92 ++++++++++++
 contrib/odfsign/odfsign.1                   | 217 ++++++++++++++++++++++++++++
 contrib/odfsign/odfsign.xml                 |  50 +++++++
 contrib/odfsign/testdocs/ClimateChange2.odt | Bin 0 -> 57571 bytes
 contrib/odfsign/testdocs/ClimateChange3.odt | Bin 0 -> 73828 bytes
 odf/opendocument.py                         |   1 +
 7 files changed, 374 insertions(+)

diff --git a/contrib/odfsign/Makefile b/contrib/odfsign/Makefile
new file mode 100644
index 0000000..8fdab7d
--- /dev/null
+++ b/contrib/odfsign/Makefile
@@ -0,0 +1,14 @@
+all: odf odfsign.1 
+
+txt: odfsign.txt
+
+%.1: %.xml 
+	xmlto man $<
+
+%.txt: %.xml 
+	xmlto txt $<
+
+clean:
+	rm -f *.txt odf
+odf:
+	ln -s ../../odf
diff --git a/contrib/odfsign/odfsign b/contrib/odfsign/odfsign
new file mode 100755
index 0000000..216ecbb
--- /dev/null
+++ b/contrib/odfsign/odfsign
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2006 Søren Roug, European Environment Agency
+#
+# This is free software.  You may redistribute it under the terms
+# of the Apache license and the GNU General Public License Version
+# 2 or at your option any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#
+# Contributor(s):
+#
+# Requires PyXML
+import sha,base64,zipfile,sys
+from xml.dom.ext.reader import PyExpat
+from xml.dom.ext.c14n import Canonicalize
+import StringIO
+
+
+def data_digest(data):
+    return base64.b64encode(sha.new(data).digest())
+
+def xml_digest(dom):
+    s = StringIO.StringIO()
+    Canonicalize(dom,s)
+    canon = s.getvalue().encode('utf-8')
+    return data_digest(canon)
+
+def get_signatureproperty(dom, ref):
+    property_list = dom.getElementsByTagNameNS('http://www.w3.org/2000/09/xmldsig#','SignatureProperty')
+    for p in property_list:
+       id = p.getAttributeNS(None,'Id')
+       if ref == id: return p
+    return None
+
+def exitwithusage(exitcode=2):
+    sys.stderr.write("Usage: %s inputfile\n" % sys.argv[0])
+    sys.exit(exitcode)
+    
+if __name__ == '__main__':
+    if len(sys.argv) != 2:
+        exitwithusage()
+    z = zipfile.ZipFile(sys.argv[1])
+    namelist = z.namelist()
+    if "META-INF/documentsignatures.xml" not in namelist:
+        print "This document is not signed"
+        sys.exit()
+    documentsignatures_xml = z.read('META-INF/documentsignatures.xml')
+    reader = PyExpat.Reader()
+    doc = reader.fromString(documentsignatures_xml)
+
+    signature_list = doc.getElementsByTagNameNS('http://www.w3.org/2000/09/xmldsig#','Signature')
+    print "Document has %s signature(s)" % len(signature_list)
+    signnum = 1
+    for signature in signature_list:
+        date = signature.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/","date")[0].firstChild.nodeValue
+#       print date.__dict__
+
+        print "Checking signature #%d - signed on %s" % (signnum, date),
+        refs = signature.getElementsByTagNameNS('http://www.w3.org/2000/09/xmldsig#','Reference')
+        for ref in refs:
+            status = "OK"
+            uri = ref.getAttributeNS(None,'URI')
+            digest_value = ref.getElementsByTagNameNS('http://www.w3.org/2000/09/xmldsig#','DigestValue')[0].firstChild.nodeValue
+            if uri[0] != '#':
+                document = z.read(uri)
+                if uri[-4:] == ".xml" and len(document) != 0:
+                    dom = PyExpat.Reader().fromString(document)
+                    digest_actual = xml_digest(dom)
+                else:
+                    digest_actual = data_digest(document)
+            else:
+                # FIXME
+                # fragments aren't canonicalized. See http://www.w3.org/TR/xmldsig-core/#sec-URI
+                xmlfragment = get_signatureproperty(doc, uri[1:])
+                if xmlfragment is None:
+                    continue
+                digest_actual = digest_value
+                #digest_actual  = xml_digest(xmlfragment)
+            if digest_value != digest_actual:
+                status = "failed"
+
+        print status
+        signnum += 1
+
diff --git a/contrib/odfsign/odfsign.1 b/contrib/odfsign/odfsign.1
new file mode 100644
index 0000000..e135af0
--- /dev/null
+++ b/contrib/odfsign/odfsign.1
@@ -0,0 +1,217 @@
+.\"     Title: odfsign
+.\"    Author: S\(/oren Roug
+.\" Generator: DocBook XSL Stylesheets v1.74.0 <http://docbook.sf.net/>
+.\"      Date: 03/16/2009
+.\"    Manual: User commands
+.\"    Source: odfpy
+.\"  Language: English
+.\"
+.TH "ODFSIGN" "1" "03/16/2009" "odfpy" "User commands"
+.\" -----------------------------------------------------------------
+.\" * (re)Define some macros
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" toupper - uppercase a string (locale-aware)
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de toupper
+.tr aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
+\\$*
+.tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" SH-xref - format a cross-reference to an SH section
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de SH-xref
+.ie n \{\
+.\}
+.toupper \\$*
+.el \{\
+\\$*
+.\}
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" SH - level-one heading that works better for non-TTY output
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de1 SH
+.\" put an extra blank line of space above the head in non-TTY output
+.if t \{\
+.sp 1
+.\}
+.sp \\n[PD]u
+.nr an-level 1
+.set-an-margin
+.nr an-prevailing-indent \\n[IN]
+.fi
+.in \\n[an-margin]u
+.ti 0
+.HTML-TAG ".NH \\n[an-level]"
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+\." make the size of the head bigger
+.ps +3
+.ft B
+.ne (2v + 1u)
+.ie n \{\
+.\" if n (TTY output), use uppercase
+.toupper \\$*
+.\}
+.el \{\
+.nr an-break-flag 0
+.\" if not n (not TTY), use normal case (not uppercase)
+\\$1
+.in \\n[an-margin]u
+.ti 0
+.\" if not n (not TTY), put a border/line under subheading
+.sp -.6
+\l'\n(.lu'
+.\}
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" SS - level-two heading that works better for non-TTY output
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de1 SS
+.sp \\n[PD]u
+.nr an-level 1
+.set-an-margin
+.nr an-prevailing-indent \\n[IN]
+.fi
+.in \\n[IN]u
+.ti \\n[SN]u
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.ps \\n[PS-SS]u
+\." make the size of the head bigger
+.ps +2
+.ft B
+.ne (2v + 1u)
+.if \\n[.$] \&\\$*
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" BB/BE - put background/screen (filled box) around block of text
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de BB
+.if t \{\
+.sp -.5
+.br
+.in +2n
+.ll -2n
+.gcolor red
+.di BX
+.\}
+..
+.de EB
+.if t \{\
+.if "\\$2"adjust-for-leading-newline" \{\
+.sp -1
+.\}
+.br
+.di
+.in
+.ll
+.gcolor
+.nr BW \\n(.lu-\\n(.i
+.nr BH \\n(dn+.5v
+.ne \\n(BHu+.5v
+.ie "\\$2"adjust-for-leading-newline" \{\
+\M[\\$1]\h'1n'\v'+.5v'\D'P \\n(BWu 0 0 \\n(BHu -\\n(BWu 0 0 -\\n(BHu'\M[]
+.\}
+.el \{\
+\M[\\$1]\h'1n'\v'-.5v'\D'P \\n(BWu 0 0 \\n(BHu -\\n(BWu 0 0 -\\n(BHu'\M[]
+.\}
+.in 0
+.sp -.5v
+.nf
+.BX
+.in
+.sp .5v
+.fi
+.\}
+..
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" BM/EM - put colored marker in margin next to block of text
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.de BM
+.if t \{\
+.br
+.ll -2n
+.gcolor red
+.di BX
+.\}
+..
+.de EM
+.if t \{\
+.br
+.di
+.ll
+.gcolor
+.nr BH \\n(dn
+.ne \\n(BHu
+\M[\\$1]\D'P -.75n 0 0 \\n(BHu -(\\n[.i]u - \\n(INu - .75n) 0 0 -\\n(BHu'\M[]
+.in 0
+.nf
+.BX
+.in
+.fi
+.\}
+..
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "Name"
+odfsign \- Verify a signed ODF document
+.SH "Synopsis"
+.fam C
+.HP \w'\fBodfsign\fR\ 'u
+\fBodfsign\fR \fIpath\fR
+.fam
+.SH "Description"
+.PP
+\fBodfsign\fR
+checks that the checksums used in the signature are correct\&.
+\fIIt does not check that the x509 digest is correct!\fR
+Therefore it is currently of little use\&.
+.PP
+"Path" is assumed to be an OpenDocument file of text, spreadsheet or presentation type\&.
+.SH "Example"
+.sp
+.if n \{\
+.RS 4
+.\}
+.fam C
+.ps -1
+.nf
+.if t \{\
+.sp -1
+.\}
+.BB lightgray adjust-for-leading-newline
+.sp -1
+
+odfsign odf\-file
+.EB lightgray adjust-for-leading-newline
+.if t \{\
+.sp 1
+.\}
+.fi
+.fam
+.ps +1
+.if n \{\
+.RE
+.\}
+.SH "See Also"
+.PP
+http://www\&.w3\&.org/TR/xmldsig\-core
+.SH "Author"
+.PP
+\fBS\(/oren Roug\fR
+.RS 4
+Original author
+.RE
diff --git a/contrib/odfsign/odfsign.xml b/contrib/odfsign/odfsign.xml
new file mode 100644
index 0000000..f268f28
--- /dev/null
+++ b/contrib/odfsign/odfsign.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" ?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<refentry id="odfsign">
+  <refentryinfo>
+    <productname>odfpy</productname>
+    <author><firstname>Søren</firstname><surname>Roug</surname>
+    <contrib>Original author</contrib>
+    </author>
+  </refentryinfo>
+  <refmeta>
+    <refentrytitle>odfsign</refentrytitle>
+    <manvolnum>1</manvolnum>
+    <refmiscinfo class="manual">User commands</refmiscinfo>
+  </refmeta>
+<refnamediv>
+<refname>odfsign</refname>
+<refpurpose>Verify a signed ODF document</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+<cmdsynopsis>
+    <command>odfsign</command>
+    <arg choice="plain"><replaceable>path</replaceable></arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para><command>odfsign</command> checks that the checksums
+used in the signature are correct.
+<emphasis>It does not check that the x509 digest is correct!</emphasis>
+Therefore it is currently of little use.
+</para>
+<para>
+"Path" is assumed to be an
+OpenDocument file of text, spreadsheet or presentation type.
+</para>
+</refsect1>
+<refsect1><title>Example</title>
+<screen>
+odfsign odf-file
+</screen>
+</refsect1>
+<refsect1><title>See Also</title>
+<para>
+http://www.w3.org/TR/xmldsig-core
+</para>
+</refsect1>
+</refentry>
+
diff --git a/contrib/odfsign/testdocs/ClimateChange2.odt b/contrib/odfsign/testdocs/ClimateChange2.odt
new file mode 100644
index 0000000..f4fa709
Binary files /dev/null and b/contrib/odfsign/testdocs/ClimateChange2.odt differ
diff --git a/contrib/odfsign/testdocs/ClimateChange3.odt b/contrib/odfsign/testdocs/ClimateChange3.odt
new file mode 100644
index 0000000..b380556
Binary files /dev/null and b/contrib/odfsign/testdocs/ClimateChange3.odt differ
diff --git a/odf/opendocument.py b/odf/opendocument.py
index 2744c25..df8af27 100644
--- a/odf/opendocument.py
+++ b/odf/opendocument.py
@@ -394,6 +394,7 @@ class OpenDocument:
 
         # Write any extra files
         for op in self._extra:
+            if op.filename == "META-INF/documentsignatures.xml": continue # Don't save signatures
             self.manifest.addElement(manifest.FileEntry(fullpath=op.filename, mediatype=op.mediatype))
             zi = zipfile.ZipInfo(op.filename.encode('utf-8'), self._now)
             zi.compress_type = zipfile.ZIP_DEFLATED

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-odf.git



More information about the Python-modules-commits mailing list