Skip to content

Commit 96cb75e

Browse files
committed
Extend XAdES LTA signatures
IB-7995 Signed-off-by: Raul Metsma <[email protected]>
1 parent 72437de commit 96cb75e

21 files changed

+332
-264
lines changed

examples/DigiDocCSharp/DigiDocCSharp.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<TargetFramework>net472</TargetFramework>
44
<OutputType>Exe</OutputType>
55
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
6-
<AssemblyVersion>0.4.0.0</AssemblyVersion>
7-
<FileVersion>0.4.0.0</FileVersion>
6+
<AssemblyVersion>0.5.0.0</AssemblyVersion>
7+
<FileVersion>0.5.0.0</FileVersion>
88
<Copyright>Copyright © 2015</Copyright>
99
</PropertyGroup>
1010
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">

examples/DigiDocCSharp/Program.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,7 @@ private static void Websign(string[] args)
154154
b.addDataFile(args[i], "application/octet-stream");
155155
}
156156

157-
X509Certificate cert = new X509Certificate();
158-
cert.Import(args[args.Length - 2]);
157+
var cert = new X509Certificate(args[args.Length - 2]);
159158
Signature c = b.prepareWebSignature(cert.Export(X509ContentType.Cert), "time-stamp");
160159
Console.WriteLine("Signature method: " + c.signatureMethod());
161160
Console.WriteLine("Digest to sign: " + BitConverter.ToString(c.dataToSign()).Replace("-", string.Empty));
@@ -207,7 +206,13 @@ private static void Verify(string file)
207206
Console.WriteLine();
208207

209208
Console.WriteLine("Time: " + s.trustedSigningTime());
210-
Console.WriteLine("Cert: " + new X509Certificate2(s.signingCertificateDer()).Subject);
209+
Console.WriteLine("Cert: " + s.signingCertificate().Subject);
210+
Console.WriteLine("TimeStamp: " + s.TimeStampCertificate().Subject);
211+
foreach (TSAInfo tsaInfo in s.ArchiveTimeStamps())
212+
{
213+
Console.WriteLine("Archive Time: " + tsaInfo.time);
214+
Console.WriteLine("Archive Cert: " + tsaInfo.cert.Subject);
215+
}
211216

212217
s.validate();
213218
Console.WriteLine("Signature is valid");

examples/java/src/main/java/ee/ria/libdigidocpp/libdigidocpp.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,12 @@ static void verify(String file) {
149149
System.out.println();
150150

151151
System.out.println("Time: " + signature.trustedSigningTime());
152-
System.out.println("Cert: " + toX509(signature.signingCertificateDer()).getSubjectDN().toString());
152+
System.out.println("Cert: " + signature.signingCertificate().getSubjectDN().toString());
153+
System.out.println("TimeStamp Cert: " + signature.TimeStampCertificate().getSubjectDN().toString());
154+
for(TSAInfo tsaInfo : signature.ArchiveTimeStamps()) {
155+
System.out.println("Archive Time: " + tsaInfo.getTime());
156+
System.out.println("Archive Cert: " + tsaInfo.getCert().getSubjectDN().toString());
157+
}
153158

154159
try
155160
{
@@ -171,7 +176,7 @@ static void verify(String file) {
171176
}
172177

173178
static void version() {
174-
System.out.println("DigiDocJAVA 0.3 libdigidocpp " + digidoc.version());
179+
System.out.println("DigiDocJAVA 0.4 libdigidocpp " + digidoc.version());
175180
}
176181

177182
static X509Certificate toX509(byte[] der) throws CertificateException {

libdigidocpp.i

Lines changed: 89 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ extern "C"
6060
SWIGEXPORT int SWIGSTDCALL ByteVector_size(void *ptr) {
6161
return static_cast<std::vector<unsigned char>*>(ptr)->size();
6262
}
63+
SWIGEXPORT void SWIGSTDCALL ByteVector_free(void *ptr) {
64+
delete static_cast<std::vector<unsigned char>*>(ptr);
65+
}
6366
SWIGEXPORT void* SWIGSTDCALL ByteVector_to(unsigned char *data, int size) {
6467
return new std::vector<unsigned char>(data, data + size);
6568
}
@@ -72,61 +75,11 @@ extern "C"
7275
public static extern global::System.IntPtr ByteVector_data(global::System.IntPtr data);
7376
[global::System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="ByteVector_size")]
7477
public static extern int ByteVector_size(global::System.IntPtr data);
78+
[global::System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="ByteVector_free")]
79+
public static extern void ByteVector_free(global::System.IntPtr data);
7580
[global::System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="ByteVector_to")]
7681
public static extern global::System.IntPtr ByteVector_to(
77-
[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray)]byte[] data, int size);
78-
79-
public class UTF8Marshaler : global::System.Runtime.InteropServices.ICustomMarshaler {
80-
static UTF8Marshaler static_instance = new UTF8Marshaler();
81-
82-
public global::System.IntPtr MarshalManagedToNative(object managedObj) {
83-
if (managedObj == null)
84-
return global::System.IntPtr.Zero;
85-
if (!(managedObj is string))
86-
throw new global::System.Runtime.InteropServices.MarshalDirectiveException(
87-
"UTF8Marshaler must be used on a string.");
88-
89-
// not null terminated
90-
byte[] strbuf = global::System.Text.Encoding.UTF8.GetBytes((string)managedObj);
91-
global::System.IntPtr buffer = global::System.Runtime.InteropServices.Marshal.AllocHGlobal(strbuf.Length + 1);
92-
global::System.Runtime.InteropServices.Marshal.Copy(strbuf, 0, buffer, strbuf.Length);
93-
94-
// write the terminating null
95-
global::System.Runtime.InteropServices.Marshal.WriteByte(buffer + strbuf.Length, 0);
96-
return buffer;
97-
}
98-
99-
public unsafe object MarshalNativeToManaged(global::System.IntPtr pNativeData) {
100-
byte* walk = (byte*)pNativeData;
101-
102-
// find the end of the string
103-
while (*walk != 0) {
104-
walk++;
105-
}
106-
int length = (int)(walk - (byte*)pNativeData);
107-
108-
// should not be null terminated
109-
byte[] strbuf = new byte[length];
110-
// skip the trailing null
111-
global::System.Runtime.InteropServices.Marshal.Copy((global::System.IntPtr)pNativeData, strbuf, 0, length);
112-
return global::System.Text.Encoding.UTF8.GetString(strbuf);
113-
}
114-
115-
public void CleanUpNativeData(global::System.IntPtr pNativeData) {
116-
global::System.Runtime.InteropServices.Marshal.FreeHGlobal(pNativeData);
117-
}
118-
119-
public void CleanUpManagedData(object managedObj) {
120-
}
121-
122-
public int GetNativeDataSize() {
123-
return -1;
124-
}
125-
126-
public static global::System.Runtime.InteropServices.ICustomMarshaler GetInstance(string cookie) {
127-
return static_instance;
128-
}
129-
}
82+
[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray)]byte[] data, int size);
13083
%}
13184

13285
#ifdef SWIGJAVA
@@ -138,45 +91,95 @@ extern "C"
13891
jenv->ReleaseByteArrayElements($input, $input_ptr, JNI_ABORT);
13992
%}
14093
%typemap(out) std::vector<unsigned char> %{
141-
jresult = jenv->NewByteArray((&result)->size());
142-
jenv->SetByteArrayRegion(jresult, 0, (&result)->size(), (const jbyte*)(&result)->data());
94+
$result = jenv->NewByteArray((&result)->size());
95+
jenv->SetByteArrayRegion($result, 0, (&result)->size(), (const jbyte*)(&result)->data());
14396
%}
144-
%typemap(jtype) std::vector<unsigned char> "byte[]"
97+
%typemap(out) digidoc::X509Cert %{
98+
std::vector<unsigned char> temp = $1;
99+
$result = jenv->NewByteArray(temp.size());
100+
jenv->SetByteArrayRegion($result, 0, temp.size(), (const jbyte*)temp.data());
101+
%}
102+
%typemap(out) digidoc::X509Cert * %{
103+
std::vector<unsigned char> temp = *$1;
104+
$result = jenv->NewByteArray(temp.size());
105+
jenv->SetByteArrayRegion($result, 0, temp.size(), (const jbyte*)temp.data());
106+
%}
107+
%typemap(jtype) std::vector<unsigned char>, digidoc::X509Cert, digidoc::X509Cert * "byte[]"
145108
%typemap(jstype) std::vector<unsigned char> "byte[]"
146-
%typemap(jni) std::vector<unsigned char> "jbyteArray"
147-
%typemap(javain) std::vector<unsigned char> "$javainput"
109+
%typemap(jstype) digidoc::X509Cert, digidoc::X509Cert* "java.security.cert.X509Certificate"
110+
%typemap(jni) std::vector<unsigned char>, digidoc::X509Cert, digidoc::X509Cert * "jbyteArray"
111+
%typemap(javain) std::vector<unsigned char>, digidoc::X509Cert "$javainput"
148112
%typemap(javaout) std::vector<unsigned char> {
149113
return $jnicall;
150114
}
115+
%typemap(javaout, throws="java.security.cert.CertificateException, java.io.IOException") digidoc::X509Cert, digidoc::X509Cert * {
116+
byte[] der = $jnicall;
117+
java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X509");
118+
try (java.io.ByteArrayInputStream is = new java.io.ByteArrayInputStream(der)) {
119+
return (java.security.cert.X509Certificate) cf.generateCertificate(is);
120+
}
121+
}
122+
151123
#elif defined(SWIGCSHARP)
152124
%typemap(cstype) std::vector<unsigned char> "byte[]"
153-
%typemap(csin,
154-
pre= " global::System.IntPtr cPtr$csinput = digidocPINVOKE.ByteVector_to($csinput, $csinput.Length);
155-
global::System.Runtime.InteropServices.HandleRef handleRef$csinput = new global::System.Runtime.InteropServices.HandleRef(this, cPtr$csinput);"
125+
%typemap(cstype) digidoc::X509Cert, digidoc::X509Cert* "System.Security.Cryptography.X509Certificates.X509Certificate2"
126+
%typemap(csin, pre= " global::System.IntPtr cPtr$csinput = digidocPINVOKE.ByteVector_to($csinput, $csinput.Length);
127+
var handleRef$csinput = new global::System.Runtime.InteropServices.HandleRef(this, cPtr$csinput);"
156128
) std::vector<unsigned char> "handleRef$csinput"
129+
%typemap(freearg) std::vector<unsigned char>
130+
%{ delete $1; %}
157131
%typemap(csout, excode=SWIGEXCODE) std::vector<unsigned char> {
158-
global::System.IntPtr data = $imcall;$excode
159-
byte[] result = new byte[$modulePINVOKE.ByteVector_size(data)];
160-
global::System.Runtime.InteropServices.Marshal.Copy($modulePINVOKE.ByteVector_data(data), result, 0, result.Length);
161-
return result;
162-
}
163-
#elif defined(SWIGPYTHON)
164-
%typemap(in) std::vector<unsigned char> %{
165-
if (PyBytes_Check($input)) {
166-
const char *data = PyBytes_AsString($input);
167-
$1 = new std::vector<unsigned char>(data, data + PyBytes_Size($input));
168-
} else if (PyString_Check($input)) {
169-
const char *data = PyString_AsString($input);
170-
$1 = new std::vector<unsigned char>(data, data + PyString_Size($input));
171-
} else {
172-
PyErr_SetString(PyExc_TypeError, "not a bytes");
173-
SWIG_fail;
132+
global::System.IntPtr cPtr = $imcall;$excode
133+
byte[] result = new byte[$modulePINVOKE.ByteVector_size(cPtr)];
134+
global::System.Runtime.InteropServices.Marshal.Copy($modulePINVOKE.ByteVector_data(cPtr), result, 0, result.Length);
135+
$modulePINVOKE.ByteVector_free(cPtr);
136+
return result;
137+
}
138+
%typemap(csout, excode=SWIGEXCODE) digidoc::X509Cert {
139+
global::System.IntPtr cPtr = $imcall;$excode
140+
byte[] der = new byte[$modulePINVOKE.ByteVector_size(cPtr)];
141+
global::System.Runtime.InteropServices.Marshal.Copy($modulePINVOKE.ByteVector_data(cPtr), der, 0, der.Length);
142+
var result = new System.Security.Cryptography.X509Certificates.X509Certificate2(der);
143+
$modulePINVOKE.ByteVector_free(cPtr);
144+
return result;
174145
}
175-
%}
146+
%typemap(csvarout, excode=SWIGEXCODE2) digidoc::X509Cert * %{
147+
get {
148+
global::System.IntPtr cPtr = $imcall;$excode
149+
byte[] der = new byte[$modulePINVOKE.ByteVector_size(cPtr)];
150+
global::System.Runtime.InteropServices.Marshal.Copy($modulePINVOKE.ByteVector_data(cPtr), der, 0, der.Length);
151+
var result = new System.Security.Cryptography.X509Certificates.X509Certificate2(der);
152+
$modulePINVOKE.ByteVector_free(cPtr);
153+
return result;
154+
} %}
155+
%typemap(out) std::vector<unsigned char> %{ $result = new std::vector<unsigned char>(std::move($1)); %}
156+
%typemap(out) digidoc::X509Cert %{ $result = new std::vector<unsigned char>($1); %}
157+
158+
#elif defined(SWIGPYTHON)
159+
%typemap(in) std::vector<unsigned char> %{
160+
if (PyBytes_Check($input)) {
161+
const char *data = PyBytes_AsString($input);
162+
$1 = new std::vector<unsigned char>(data, data + PyBytes_Size($input));
163+
} else if (PyString_Check($input)) {
164+
const char *data = PyString_AsString($input);
165+
$1 = new std::vector<unsigned char>(data, data + PyString_Size($input));
166+
} else {
167+
PyErr_SetString(PyExc_TypeError, "not a bytes");
168+
SWIG_fail;
169+
}
170+
%}
176171
%typemap(out) std::vector<unsigned char>
177172
%{ $result = PyBytes_FromStringAndSize((const char*)(&result)->data(), (&result)->size()); %}
178173
%typemap(freearg) std::vector<unsigned char>
179174
%{ delete $1; %}
175+
%typemap(out) digidoc::X509Cert {
176+
std::vector<unsigned char> temp = $1;
177+
$result = PyBytes_FromStringAndSize((const char*)temp.data(), temp.size());
178+
}
179+
%typemap(out) digidoc::X509Cert * {
180+
std::vector<unsigned char> temp = *$1;
181+
$result = PyBytes_FromStringAndSize((const char*)temp.data(), temp.size());
182+
}
180183
#endif
181184
%apply std::vector<unsigned char> { std::vector<unsigned char> const & };
182185

@@ -208,11 +211,6 @@ extern "C"
208211
%ignore digidoc::ConfV2::verifyServiceCert;
209212
%ignore digidoc::ConfV4::verifyServiceCerts;
210213
%ignore digidoc::ConfV5::TSCerts;
211-
%ignore digidoc::Signer::cert;
212-
%ignore digidoc::Signature::signingCertificate;
213-
%ignore digidoc::Signature::OCSPCertificate;
214-
%ignore digidoc::Signature::TimeStampCertificate;
215-
%ignore digidoc::Signature::ArchiveTimeStampCertificate;
216214
// hide stream methods, swig cannot generate usable wrappers
217215
%ignore digidoc::DataFile::saveAs(std::ostream &os) const;
218216
%ignore digidoc::Container::addAdESSignature(std::istream &signature);
@@ -231,6 +229,9 @@ extern "C"
231229
%newobject digidoc::Container::open;
232230
%newobject digidoc::Container::create;
233231

232+
%immutable digidoc::TSAInfo::cert;
233+
%immutable digidoc::TSAInfo::time;
234+
234235
%feature("director") digidoc::ContainerOpenCB;
235236

236237
%typemap(javacode) digidoc::Conf %{
@@ -260,15 +261,10 @@ def transfer(self):
260261
%include "std_vector.i"
261262
%include "std_map.i"
262263
#ifdef SWIGCSHARP
263-
namespace std {
264-
%typemap(imtype,
265-
inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]",
266-
outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]")
267-
string "string"
268-
%typemap(imtype,
269-
inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]",
270-
outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]") const string & "string"
271-
}
264+
%typemap(imtype,
265+
inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPUTF8Str)]",
266+
outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPUTF8Str)]")
267+
std::string, const std::string & "string"
272268
#endif
273269

274270
// Handle DigiDoc Export declarations
@@ -293,32 +289,8 @@ namespace std {
293289
%template(StringMap) std::map<std::string,std::string>;
294290
%template(DataFiles) std::vector<digidoc::DataFile*>;
295291
%template(Signatures) std::vector<digidoc::Signature*>;
292+
%template(TSAInfos) std::vector<digidoc::TSAInfo>;
296293

297-
// override X509Cert methods to return byte array
298-
%extend digidoc::Signer {
299-
std::vector<unsigned char> cert() const
300-
{
301-
return $self->cert();
302-
}
303-
}
304-
%extend digidoc::Signature {
305-
std::vector<unsigned char> signingCertificateDer() const
306-
{
307-
return $self->signingCertificate();
308-
}
309-
std::vector<unsigned char> OCSPCertificateDer() const
310-
{
311-
return $self->OCSPCertificate();
312-
}
313-
std::vector<unsigned char> TimeStampCertificateDer() const
314-
{
315-
return $self->TimeStampCertificate();
316-
}
317-
std::vector<unsigned char> ArchiveTimeStampCertificateDer() const
318-
{
319-
return $self->ArchiveTimeStampCertificate();
320-
}
321-
}
322294
%extend digidoc::Container {
323295
static digidoc::Container* open(const std::string &path, digidoc::ContainerOpenCB *cb)
324296
{

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ if(SWIG_FOUND)
202202
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/digidoc.py DESTINATION ${Python3_SITELIB})
203203
endif()
204204

205-
set(CMAKE_SWIG_FLAGS -dllimport digidoc_csharp -namespace digidoc)
205+
set(CMAKE_SWIG_FLAGS -namespace digidoc)
206206
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/csharp)
207207
swig_add_library(digidoc_csharp LANGUAGE csharp SOURCES ../libdigidocpp.i)
208208
target_compile_definitions(digidoc_csharp PRIVATE TARGET_NAME="$<TARGET_NAME:digidoc_csharp>")

src/DataFile.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,8 @@ DataFilePrivate::DataFilePrivate(unique_ptr<istream> &&is, string filename, stri
9898
m_size = pos < 0 ? 0 : (unsigned long)pos;
9999
}
100100

101-
vector<unsigned char> DataFilePrivate::calcDigest(const string &method) const
101+
void DataFilePrivate::digest(const Digest &digest) const
102102
{
103-
Digest digest(method);
104103
array<unsigned char, 10240> buf{};
105104
m_is->clear();
106105
m_is->seekg(0);
@@ -110,7 +109,13 @@ vector<unsigned char> DataFilePrivate::calcDigest(const string &method) const
110109
if(m_is->gcount() > 0)
111110
digest.update(buf.data(), size_t(m_is->gcount()));
112111
}
113-
return digest.result();
112+
}
113+
114+
std::vector<unsigned char> DataFilePrivate::calcDigest(const string &method) const
115+
{
116+
Digest d(method);
117+
digest(d);
118+
return d.result();
114119
}
115120

116121
void DataFilePrivate::saveAs(const string& path) const

src/DataFile_p.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
namespace digidoc
2828
{
2929

30+
class Digest;
3031
class DataFilePrivate final: public DataFile
3132
{
3233
public:
@@ -37,6 +38,7 @@ class DataFilePrivate final: public DataFile
3738
unsigned long fileSize() const final { return m_size; }
3839
std::string mediaType() const final { return m_mediatype; }
3940

41+
void digest(const Digest &method) const;
4042
std::vector<unsigned char> calcDigest(const std::string &method) const final;
4143
void saveAs(std::ostream &os) const final;
4244
void saveAs(const std::string& path) const final;

src/SiVaContainer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ unique_ptr<istream> SiVaContainer::parseDDoc(bool useHashCode)
362362
if(!useHashCode)
363363
continue;
364364
Digest calc(URI_SHA1);
365-
doc.c14n(&calc, XMLDocument::C14D_ID_1_0, dataFile);
365+
doc.c14n(calc, XMLDocument::C14D_ID_1_0, dataFile);
366366
dataFile.setProperty("ContentType", "HASHCODE");
367367
dataFile.setProperty("DigestType", "sha1");
368368
dataFile.setProperty("DigestValue", to_base64(calc.result()));

0 commit comments

Comments
 (0)