Skip to content

Commit

Permalink
[#2] File references can be added to stamps
Browse files Browse the repository at this point in the history
  • Loading branch information
kgilden committed Oct 19, 2014
1 parent c2f7f9b commit f7fefae
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 4 deletions.
96 changes: 92 additions & 4 deletions src/Native/Stamp.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

namespace KG\DigiDoc\Native;

use DOMDocument;

class Stamp
{
/**
Expand All @@ -23,8 +21,98 @@ class Stamp
/**
* @param DomDocument $dom DOM of the stamp's XML representation
*/
public function __construct(\DOMDocument $dom)
public function __construct(\DOMDocument $dom = null)
{
$this->dom = $dom ?: $this->createDom();
}

/**
* Adds a file reference to the stamp.
*
* @todo Don't allow adding files, if the stamp is signed
*
* @param string $pathInEnvelope File's relative path in the envelope
* @param string $pathToFile File's current path
*
* @return Stamp
*/
public function addFile($pathInEnvelope, $pathToFile)
{
$xpath = new \DOMXpath($this->dom);
$nodes = $xpath->query('/asic:XAdESSignatures/ds:Signature/ds:SignedInfo');

foreach ($nodes as $node) {
$this->appendRef($node, $pathInEnvelope, $pathToFile);
}

return $this;
}

public function getFileDigest($pathInEnvelope)
{
$xpath = new \DOMXpath($this->dom);
$nodes = $xpath->query(sprintf('.//ds:Reference[@URI="%s"]', $pathInEnvelope));

if ($nodes->length !== 1) {
throw new \RuntimeException(sprintf('Expected to find 1 reference node with uri "%s", found %d.', $pathInEnvelope, $nodes->length));
}

return base64_decode(str_replace("\n", '', $nodes->item(0)->textContent));
}

/**
* Appends a file reference to the stamp. Its structure is the following
*
* <ds:Reference Id="__id__" URI="__pathInEnvelope__">
* <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
* <ds:DigestValue>__b64enc_digest__</ds:DigestValue>
* </ds:Reference>
*
* @param \DOMNode $parent
* @param string $pathInEnvelope
* @param string $pathToFile
*/
private function appendRef(\DOMNode $parent, $pathInEnvelope, $pathToFile)
{
$prefix = $parent->prefix;
$nsUri = $parent->namespaceURI;

$ref = $this->dom->createElementNS($nsUri, $prefix . ':Reference');
$ref->setAttribute('Id', uniqid());
$ref->setAttribute('URI', $pathInEnvelope);

$digestMethod = $this->dom->createElementNS($nsUri, $prefix . ':DigestMethod');
$digestMethod->setAttribute('Algorithm', 'http://www.w3.org/2001/04/xmlenc#sha256');

$digestValue = $this->dom->createElementNS($nsUri, $prefix . ':DigestValue', $this->digestFile('sha256', $pathToFile));

$ref
->appendChild($digestMethod)
->appendChild($digestValue)
;

$parent->appendChild($ref);
}

/**
* @return \DOMDocument
*/
private function createDom()
{
$dom = new \DOMDocument();
$dom->load(__DIR__ . '/stamp.xml');

return $dom;
}

/**
* @param string $algo
* @param string $path
*
* @return string
*/
private function digestFile($algo, $path)
{
$this->dom = $dom;
return chunk_split(base64_encode(hash_file($algo, $path, true)), 64, "\n");
}
}
99 changes: 99 additions & 0 deletions src/Native/stamp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<asic:XAdESSignatures xmlns:asic="http://uri.etsi.org/02918/v1.2.1#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">

<ds:Signature Id="">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<!--
<ds:Reference Id="S0-RefId0" URI="hello.txt">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue />
</ds:Reference>
<ds:Reference Id="S0-RefId1" Type="http://uri.etsi.org/01903#SignedProperties" URI="#S0-SignedProperties">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue />
</ds:Reference>
-->
</ds:SignedInfo>
<ds:SignatureValue Id="" />
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate />
</ds:X509Data>
</ds:KeyInfo>
<ds:Object>
<xades:QualifyingProperties Target="">
<xades:SignedProperties Id="">
<xades:SignedSignatureProperties>
<xades:SigningTime />
<xades:SigningCertificate>
<xades:Cert>
<xades:CertDigest>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue />
</xades:CertDigest>
<xades:IssuerSerial>
<!--
<ds:X509IssuerName>[email protected],CN=ESTEID-SK 2011,O=AS Sertifitseerimiskeskus,C=EE</ds:X509IssuerName>
<ds:X509SerialNumber>42514520234216594820678577464228965245</ds:X509SerialNumber>
-->
</xades:IssuerSerial>
</xades:Cert>
</xades:SigningCertificate>
<xades:SignaturePolicyIdentifier>
<xades:SignaturePolicyId>
<xades:SigPolicyId>
<xades:Identifier Qualifier="OIDAsURN">urn:oid:1.3.6.1.4.1.10015.1000.3.2.1</xades:Identifier>
<xades:Description>BDOC – FORMAT FOR DIGITAL SIGNATURES</xades:Description>
</xades:SigPolicyId>
<xades:SigPolicyHash>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue />
</xades:SigPolicyHash>
<xades:SigPolicyQualifiers>
<xades:SigPolicyQualifier>
<xades:SPURI>https://www.sk.ee/repository/bdoc-spec21.pdf</xades:SPURI>
</xades:SigPolicyQualifier>
</xades:SigPolicyQualifiers>
</xades:SignaturePolicyId>
</xades:SignaturePolicyIdentifier>
<xades:SignatureProductionPlace>
<xades:City />
<xades:StateOrProvince />
<xades:PostalCode />
<xades:CountryName />
</xades:SignatureProductionPlace>
<xades:SignerRole>
<xades:ClaimedRoles>
<xades:ClaimedRole />
</xades:ClaimedRoles>
</xades:SignerRole>
</xades:SignedSignatureProperties>
<xades:SignedDataObjectProperties>
<!--
<xades:DataObjectFormat ObjectReference="#S0-RefId0">
<xades:MimeType>application/octet-stream</xades:MimeType>
</xades:DataObjectFormat>
-->
</xades:SignedDataObjectProperties>
</xades:SignedProperties>
<xades:UnsignedProperties>
<xades:UnsignedSignatureProperties>
<xades:CertificateValues>
<!-- <xades:EncapsulatedX509Certificate Id="S0-RESPONDER_CERT" /> -->
<!-- <xades:EncapsulatedX509Certificate Id="S0-CA-CERT" /> -->
</xades:CertificateValues>
<xades:RevocationValues>
<xades:OCSPValues>
<xades:EncapsulatedOCSPValue Id=""></xades:EncapsulatedOCSPValue>
</xades:OCSPValues>
</xades:RevocationValues>
</xades:UnsignedSignatureProperties>
</xades:UnsignedProperties>
</xades:QualifyingProperties>
</ds:Object>
</ds:Signature>

</asic:XAdESSignatures>
32 changes: 32 additions & 0 deletions tests/Native/StampTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the DigiDoc package.
*
* (c) Kristen Gilden <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace KG\DigiDoc\Tests\Native;

use KG\DigiDoc\Native\Stamp;
use VirtualFileSystem\FileSystem;

class StampTest extends \PHPUnit_Framework_TestCase
{
public function testAddFile()
{
$fs = new FileSystem();
file_put_contents($fs->path('/foo.txt'), $text = 'Hello, world!');

$stamp = new Stamp();
$stamp->addFile('example.txt', $fs->path('/foo.txt'));

$this->assertEquals(
hash('sha256', $text, true),
$stamp->getFileDigest('example.txt')
);
}
}

0 comments on commit f7fefae

Please sign in to comment.