xmldsign 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +18 -0
  2. data/.idea/.name +1 -0
  3. data/.idea/.rakeTasks +7 -0
  4. data/.idea/encodings.xml +5 -0
  5. data/.idea/misc.xml +25 -0
  6. data/.idea/modules.xml +9 -0
  7. data/.idea/scopes/scope_settings.xml +5 -0
  8. data/.idea/vcs.xml +7 -0
  9. data/Gemfile +4 -0
  10. data/LICENSE.txt +22 -0
  11. data/README.md +29 -0
  12. data/Rakefile +1 -0
  13. data/ext/xmldsign/extconf.rb +3 -0
  14. data/ext/xmldsign/gost89.c +409 -0
  15. data/ext/xmldsign/gost89.h +96 -0
  16. data/ext/xmldsign/gosthash.c +254 -0
  17. data/ext/xmldsign/gosthash.h +48 -0
  18. data/ext/xmldsign/xmldsign_ext.bundle +0 -0
  19. data/ext/xmldsign/xmldsign_ext.c +66 -0
  20. data/ext/xmldsign/xmldsign_ext.h +18 -0
  21. data/lib/xmldsign/algorithms.rb +84 -0
  22. data/lib/xmldsign/digests/gost.rb +30 -0
  23. data/lib/xmldsign/document.rb +19 -0
  24. data/lib/xmldsign/error.rb +2 -0
  25. data/lib/xmldsign/signature.rb +64 -0
  26. data/lib/xmldsign/signed_info.rb +7 -0
  27. data/lib/xmldsign/transforms.rb +17 -0
  28. data/lib/xmldsign/version.rb +3 -0
  29. data/lib/xmldsign.rb +21 -0
  30. data/spec/assets/act-birth-for-sign.xml +118 -0
  31. data/spec/assets/act-birth-with-comment-for-sign.xml +105 -0
  32. data/spec/assets/act-death-for-sign.xml +75 -0
  33. data/spec/assets/act-death-with-empty-tags-for-sign.xml +75 -0
  34. data/spec/assets/csr.pem +11 -0
  35. data/spec/assets/private.key.pem +15 -0
  36. data/spec/assets/private.passw.key.pem +18 -0
  37. data/spec/assets/public.key.pem +6 -0
  38. data/spec/assets/signed-act-birth-with-comment.xml +134 -0
  39. data/spec/assets/signed-act-birth.xml +116 -0
  40. data/spec/assets/signed-act-changed-ns-order.xml +137 -0
  41. data/spec/assets/signed-act-changed-prefixes.xml +136 -0
  42. data/spec/assets/signed-act-changed-xml-comments.xml +146 -0
  43. data/spec/assets/signed-act-death-with-empty-tags.xml +117 -0
  44. data/spec/assets/signed-act-death.xml +117 -0
  45. data/spec/assets/signed-act-wrong-canon-alg.xml +34 -0
  46. data/spec/assets/signed-act-wrong-data.xml +133 -0
  47. data/spec/assets/signed-act-wrong-sign-alg.xml +34 -0
  48. data/spec/assets/signed-act-wrong-signature-value.xml +133 -0
  49. data/spec/assets/signed-act-wrong-trans-alg.xml +34 -0
  50. data/spec/assets/signed-act-wrong-trans-algs-order.xml +34 -0
  51. data/spec/assets/signed-act-wrong-trans-count.xml +31 -0
  52. data/spec/assets/signed-act-wrong-trans0-alg.xml +34 -0
  53. data/spec/assets/signed-act-wrong-transxslt-alg.xml +34 -0
  54. data/spec/assets/signed-info-for-act-birth.xml +15 -0
  55. data/spec/assets/signed.test.xml +103 -0
  56. data/spec/assets/unsigned.test.xml +14 -0
  57. data/spec/assets/x509.crt +13 -0
  58. data/spec/spec_helper.rb +22 -0
  59. data/spec/xmldsign/sign_spec.rb +24 -0
  60. data/xmldsign.gemspec +29 -0
  61. metadata +254 -0
@@ -0,0 +1,254 @@
1
+ /**********************************************************************
2
+ * gosthash.c *
3
+ * Copyright (c) 2005-2006 Cryptocom LTD *
4
+ * This file is distributed under the same license as OpenSSL *
5
+ * *
6
+ * Implementation of GOST R 34.11-94 hash function *
7
+ * uses on gost89.c and gost89.h Doesn't need OpenSSL *
8
+ **********************************************************************/
9
+ #include <string.h>
10
+
11
+ #include "gost89.h"
12
+ #include "gosthash.h"
13
+
14
+
15
+ /* Use OPENSSL_malloc for memory allocation if compiled with
16
+ * -DOPENSSL_BUILD, and libc malloc otherwise
17
+ */
18
+ #ifndef MYALLOC
19
+ # ifdef OPENSSL_BUILD
20
+ # include <openssl/crypto.h>
21
+ # define MYALLOC(size) OPENSSL_malloc(size)
22
+ # define MYFREE(ptr) OPENSSL_free(ptr)
23
+ # else
24
+ # define MYALLOC(size) malloc(size)
25
+ # define MYFREE(ptr) free(ptr)
26
+ # endif
27
+ #endif
28
+ /* Following functions are various bit meshing routines used in
29
+ * GOST R 34.11-94 algorithms */
30
+ static void swap_bytes (byte *w, byte *k)
31
+ {
32
+ int i,j;
33
+ for (i=0;i<4;i++)
34
+ for (j=0;j<8;j++)
35
+ k[i+4*j]=w[8*i+j];
36
+ }
37
+
38
+ /* was A_A */
39
+ static void circle_xor8 (const byte *w, byte *k)
40
+ {
41
+ byte buf[8];
42
+ int i;
43
+ memcpy(buf,w,8);
44
+ memcpy(k,w+8,24);
45
+ for(i=0;i<8;i++)
46
+ k[i+24]=buf[i]^k[i];
47
+ }
48
+
49
+ /* was R_R */
50
+ static void transform_3 (byte *data)
51
+ {
52
+ unsigned short int acc;
53
+ acc=(data[0]^data[2]^data[4]^data[6]^data[24]^data[30])|
54
+ ((data[1]^data[3]^data[5]^data[7]^data[25]^data[31])<<8);
55
+ memmove(data,data+2,30);
56
+ data[30]=acc&0xff;
57
+ data[31]=acc>>8;
58
+ }
59
+
60
+ /* Adds blocks of N bytes modulo 2**(8*n). Returns carry*/
61
+ static int add_blocks(int n,byte *left, const byte *right)
62
+ {
63
+ int i;
64
+ int carry=0;
65
+ int sum;
66
+ for (i=0;i<n;i++)
67
+ {
68
+ sum=(int)left[i]+(int)right[i]+carry;
69
+ left[i]=sum & 0xff;
70
+ carry=sum>>8;
71
+ }
72
+ return carry;
73
+ }
74
+
75
+ /* Xor two sequences of bytes */
76
+ static void xor_blocks (byte *result,const byte *a,const byte *b,size_t len)
77
+ {
78
+ size_t i;
79
+ for (i=0;i<len;i++) result[i]=a[i]^b[i];
80
+ }
81
+
82
+ /*
83
+ * Calculate H(i+1) = Hash(Hi,Mi)
84
+ * Where H and M are 32 bytes long
85
+ */
86
+ static int hash_step(gost_ctx *c,byte *H,const byte *M)
87
+ {
88
+ byte U[32],W[32],V[32],S[32],Key[32];
89
+ int i;
90
+ /* Compute first key */
91
+ xor_blocks(W,H,M,32);
92
+ swap_bytes(W,Key);
93
+ /* Encrypt first 8 bytes of H with first key*/
94
+ gost_enc_with_key(c,Key,H,S);
95
+ /* Compute second key*/
96
+ circle_xor8(H,U);
97
+ circle_xor8(M,V);
98
+ circle_xor8(V,V);
99
+ xor_blocks(W,U,V,32);
100
+ swap_bytes(W,Key);
101
+ /* encrypt second 8 bytes of H with second key*/
102
+ gost_enc_with_key(c,Key,H+8,S+8);
103
+ /* compute third key */
104
+ circle_xor8(U,U);
105
+ U[31]=~U[31]; U[29]=~U[29]; U[28]=~U[28]; U[24]=~U[24];
106
+ U[23]=~U[23]; U[20]=~U[20]; U[18]=~U[18]; U[17]=~U[17];
107
+ U[14]=~U[14]; U[12]=~U[12]; U[10]=~U[10]; U[ 8]=~U[ 8];
108
+ U[ 7]=~U[ 7]; U[ 5]=~U[ 5]; U[ 3]=~U[ 3]; U[ 1]=~U[ 1];
109
+ circle_xor8(V,V);
110
+ circle_xor8(V,V);
111
+ xor_blocks(W,U,V,32);
112
+ swap_bytes(W,Key);
113
+ /* encrypt third 8 bytes of H with third key*/
114
+ gost_enc_with_key(c,Key,H+16,S+16);
115
+ /* Compute fourth key */
116
+ circle_xor8(U,U);
117
+ circle_xor8(V,V);
118
+ circle_xor8(V,V);
119
+ xor_blocks(W,U,V,32);
120
+ swap_bytes(W,Key);
121
+ /* Encrypt last 8 bytes with fourth key */
122
+ gost_enc_with_key(c,Key,H+24,S+24);
123
+ for (i=0;i<12;i++)
124
+ transform_3(S);
125
+ xor_blocks(S,S,M,32);
126
+ transform_3(S);
127
+ xor_blocks(S,S,H,32);
128
+ for (i=0;i<61;i++)
129
+ transform_3(S);
130
+ memcpy(H,S,32);
131
+ return 1;
132
+ }
133
+
134
+ /* Initialize gost_hash ctx - cleans up temporary structures and
135
+ * set up substitution blocks
136
+ */
137
+ int init_gost_hash_ctx(gost_hash_ctx *ctx, const gost_subst_block *subst_block)
138
+ {
139
+ memset(ctx,0,sizeof(gost_hash_ctx));
140
+ ctx->cipher_ctx = (gost_ctx *)MYALLOC(sizeof(gost_ctx));
141
+ if (!ctx->cipher_ctx)
142
+ {
143
+ return 0;
144
+ }
145
+ gost_init(ctx->cipher_ctx,subst_block);
146
+ return 1;
147
+ }
148
+
149
+ /*
150
+ * Free cipher CTX if it is dynamically allocated. Do not use
151
+ * if cipher ctx is statically allocated as in OpenSSL implementation of
152
+ * GOST hash algroritm
153
+ *
154
+ */
155
+ void done_gost_hash_ctx(gost_hash_ctx *ctx)
156
+ {
157
+ /* No need to use gost_destroy, because cipher keys are not really
158
+ * secret when hashing */
159
+ MYFREE(ctx->cipher_ctx);
160
+ }
161
+
162
+ /*
163
+ * reset state of hash context to begin hashing new message
164
+ */
165
+ int start_hash(gost_hash_ctx *ctx)
166
+ {
167
+ if (!ctx->cipher_ctx) return 0;
168
+ memset(&(ctx->H),0,32);
169
+ memset(&(ctx->S),0,32);
170
+ ctx->len = 0L;
171
+ ctx->left=0;
172
+ return 1;
173
+ }
174
+
175
+ /*
176
+ * Hash block of arbitrary length
177
+ *
178
+ *
179
+ */
180
+ int hash_block(gost_hash_ctx *ctx,const byte *block, size_t length)
181
+ {
182
+ const byte *curptr=block;
183
+ const byte *barrier=block+(length-32);/* Last byte we can safely hash*/
184
+ if (ctx->left)
185
+ {
186
+ /*There are some bytes from previous step*/
187
+ unsigned int add_bytes = 32-ctx->left;
188
+ if (add_bytes>length)
189
+ {
190
+ add_bytes = length;
191
+ }
192
+ memcpy(&(ctx->remainder[ctx->left]),block,add_bytes);
193
+ ctx->left+=add_bytes;
194
+ if (ctx->left<32)
195
+ {
196
+ return 1;
197
+ }
198
+ curptr=block+add_bytes;
199
+ hash_step(ctx->cipher_ctx,ctx->H,ctx->remainder);
200
+ add_blocks(32,ctx->S,ctx->remainder);
201
+ ctx->len+=32;
202
+ ctx->left=0;
203
+ }
204
+ while (curptr<=barrier)
205
+ {
206
+ hash_step(ctx->cipher_ctx,ctx->H,curptr);
207
+
208
+ add_blocks(32,ctx->S,curptr);
209
+ ctx->len+=32;
210
+ curptr+=32;
211
+ }
212
+ if (curptr!=block+length)
213
+ {
214
+ ctx->left=block+length-curptr;
215
+ memcpy(ctx->remainder,curptr,ctx->left);
216
+ }
217
+ return 1;
218
+ }
219
+
220
+ /*
221
+ * Compute hash value from current state of ctx
222
+ * state of hash ctx becomes invalid and cannot be used for further
223
+ * hashing.
224
+ */
225
+ int finish_hash(gost_hash_ctx *ctx,byte *hashval)
226
+ {
227
+ byte buf[32];
228
+ byte H[32];
229
+ byte S[32];
230
+ ghosthash_len fin_len=ctx->len;
231
+ byte *bptr;
232
+ memcpy(H,ctx->H,32);
233
+ memmove(S,ctx->S,32);
234
+ if (ctx->left)
235
+ {
236
+ memset(buf,0,32);
237
+ memcpy(buf,ctx->remainder,ctx->left);
238
+ hash_step(ctx->cipher_ctx,H,buf);
239
+ add_blocks(32,S,buf);
240
+ fin_len+=ctx->left;
241
+ }
242
+ memset(buf,0,32);
243
+ bptr=buf;
244
+ fin_len<<=3; /* Hash length in BITS!!*/
245
+ while(fin_len>0)
246
+ {
247
+ *(bptr++)=(byte)(fin_len&0xFF);
248
+ fin_len>>=8;
249
+ };
250
+ hash_step(ctx->cipher_ctx,H,buf);
251
+ hash_step(ctx->cipher_ctx,H,S);
252
+ memcpy(hashval,H,32);
253
+ return 1;
254
+ }
@@ -0,0 +1,48 @@
1
+ /**********************************************************************
2
+ * gosthash.h *
3
+ * Copyright (c) 2005-2006 Cryptocom LTD *
4
+ * This file is distributed under the same license as OpenSSL *
5
+ * *
6
+ * Declaration of GOST R 34.11-94 hash functions *
7
+ * uses and gost89.h Doesn't need OpenSSL *
8
+ **********************************************************************/
9
+ #ifndef GOSTHASH_H
10
+ #define GOSTHASH_H
11
+ #include "gost89.h"
12
+ #include <stdlib.h>
13
+
14
+ #if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
15
+ typedef __int64 ghosthash_len;
16
+ #elif defined(__arch64__)
17
+ typedef long ghosthash_len;
18
+ #else
19
+ typedef long long ghosthash_len;
20
+ #endif
21
+
22
+ typedef struct gost_hash_ctx {
23
+ ghosthash_len len;
24
+ gost_ctx *cipher_ctx;
25
+ int left;
26
+ byte H[32];
27
+ byte S[32];
28
+ byte remainder[32];
29
+ } gost_hash_ctx;
30
+
31
+
32
+ /* Initalizes gost hash ctx, including creation of gost cipher ctx */
33
+
34
+ int init_gost_hash_ctx(gost_hash_ctx *ctx, const gost_subst_block *subst_block);
35
+ void done_gost_hash_ctx(gost_hash_ctx *ctx);
36
+
37
+ /* Cleans up all fields, except cipher ctx preparing ctx for computing
38
+ * of new hash value */
39
+ int start_hash(gost_hash_ctx *ctx);
40
+
41
+ /* Hashes block of data */
42
+ int hash_block(gost_hash_ctx *ctx, const byte *block, size_t length);
43
+
44
+ /* Finalizes computation of hash and fills buffer (which should be at
45
+ * least 32 bytes long) with value of computed hash. */
46
+ int finish_hash(gost_hash_ctx *ctx, byte *hashval);
47
+
48
+ #endif
Binary file
@@ -0,0 +1,66 @@
1
+ #include <xmldsign_ext.h>
2
+
3
+ #ifndef O_BINARY
4
+ #define O_BINARY 0
5
+ #endif
6
+
7
+ char* substring(const char* str, size_t begin, size_t len)
8
+ {
9
+ if (str == 0 || strlen(str) == 0 || strlen(str) < begin || strlen(str) < (begin+len))
10
+ return 0;
11
+
12
+ return strndup(str + begin, len);
13
+ }
14
+
15
+ int digest(char * data, char * sum)
16
+ {
17
+ gost_subst_block *b= &GostR3411_94_CryptoProParamSet;
18
+ gost_hash_ctx ctx;
19
+
20
+ init_gost_hash_ctx(&ctx, b);
21
+
22
+ if (hash_data(&ctx, data, sum))
23
+ {
24
+ return 1;
25
+ }
26
+ else
27
+ return 0;
28
+ }
29
+
30
+ int hash_data(gost_hash_ctx *ctx, const char *data, char *sum)
31
+ {
32
+ int i;
33
+ size_t bytes = strlen(data);
34
+
35
+ start_hash(ctx);
36
+
37
+ if(bytes > 0)
38
+ hash_block(ctx, data, bytes);
39
+
40
+ finish_hash(ctx, sum);
41
+
42
+ return 1;
43
+ }
44
+
45
+ static VALUE rb_gost_digest(VALUE self)
46
+ {
47
+ char sum[32];
48
+
49
+ VALUE data;
50
+
51
+ data = rb_iv_get(self, "@data");
52
+
53
+ if( digest(StringValuePtr(data), sum) )
54
+ return rb_str_new2( substring(sum, 0, 32) );
55
+ else
56
+ return Qfalse;
57
+ }
58
+
59
+ /* Ruby Extension initializer */
60
+ void Init_xmldsign_ext() {
61
+ mXmldsign = rb_define_module("Xmldsign");
62
+ mDigests = rb_define_module_under(mXmldsign, "Digests");
63
+ cGost = rb_define_class_under(mDigests, "Gost", rb_cObject);
64
+
65
+ rb_define_method(cGost, "binary", rb_gost_digest, 0);
66
+ }
@@ -0,0 +1,18 @@
1
+ #ifndef XMLDSIGN_EXT_H
2
+ #define XMLDSIGN_EXT_H
3
+
4
+ #include <ruby.h>
5
+
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <unistd.h>
9
+ #include <limits.h>
10
+ #include <string.h>
11
+
12
+ #include "gost89.h"
13
+ #include "gosthash.h"
14
+
15
+ VALUE mXmldsign, mDigests, cGost;
16
+
17
+
18
+ #endif /* ifndef XMLDSIGN_EXT_H */
@@ -0,0 +1,84 @@
1
+ module Xmldsign
2
+ module Algorithms
3
+ def factory(uri, node)
4
+ ALGORITHMS[uri].new(node)
5
+ end
6
+
7
+ class Gostr3411
8
+ def initialize(transform_node)
9
+ end
10
+
11
+ def execute(xml)
12
+ Digests::Gost.base64(xml)
13
+ end
14
+
15
+ def openssl
16
+ @engine.digest(KEY)
17
+ end
18
+ end
19
+
20
+ class Enveloped
21
+ def initialize(transform_node)
22
+ end
23
+
24
+ def execute(doc)
25
+ doc.find_first('.//ds:Signature').remove!
26
+ doc
27
+ end
28
+ end
29
+
30
+ class XSLT
31
+ attr_reader :transform_node
32
+
33
+ def initialize(transform_node)
34
+ @transform_node = transform_node
35
+ end
36
+
37
+ def stylesheet
38
+ doc = LibXML::XML::Document.new
39
+ doc.root = transform_node.find('*[1]').first.copy(true)
40
+ LibXSLT::XSLT::Stylesheet.new(doc)
41
+ end
42
+
43
+ def execute(doc)
44
+ stylesheet.apply doc
45
+ end
46
+ end
47
+
48
+ class Canonicalization
49
+ XML_C14N_1_0 = 0
50
+ XML_C14N_EXCLUSIVE_1_0 = 1
51
+ XML_C14N_1_1 = 2
52
+
53
+ attr_reader :transform_node
54
+
55
+ def initialize(transform_node)
56
+ @transform_node = transform_node
57
+ end
58
+
59
+ def execute(doc)
60
+ raise NotImplementedError
61
+ end
62
+ end
63
+
64
+ class C14NExc < Canonicalization
65
+ def execute(doc)
66
+ doc.canonicalize mode: XML_C14N_EXCLUSIVE_1_0
67
+ end
68
+ end
69
+
70
+ ALGORITHMS = {
71
+ # Digests
72
+
73
+ "http://www.w3.org/2001/04/xmldsig-more#gostr3411" => Gostr3411,
74
+
75
+ # Transforms and Canonicalize
76
+
77
+ "http://www.w3.org/2000/09/xmldsig#enveloped-signature" => Enveloped,
78
+ "http://www.w3.org/TR/1999/REC-xslt-19991116" => XSLT,
79
+ "http://www.w3.org/2001/10/xml-exc-c14n#" => C14NExc,
80
+ }
81
+
82
+ module_function :factory
83
+ end
84
+ end
@@ -0,0 +1,30 @@
1
+ require "xmldsign/xmldsign_ext"
2
+
3
+ module Xmldsign
4
+ module Digests
5
+ class Gost
6
+ attr_reader :data
7
+
8
+ class << self
9
+ def base64(data)
10
+ new(data).base64
11
+ end
12
+ def hex(data)
13
+ new(data).hex
14
+ end
15
+ end
16
+
17
+ def initialize(data)
18
+ @data = data
19
+ end
20
+
21
+ def base64
22
+ Base64.encode64(binary).strip
23
+ end
24
+
25
+ def hex
26
+ binary.bytes.inject("") { |hex, b| hex << b.to_s(16) }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ module Xmldsign
2
+ class Document < DelegateClass(XML::Document)
3
+ def self.string(xml)
4
+ new LibXML::XML::Document.string(xml)
5
+ end
6
+
7
+ def signature
8
+ if (node = find_first('.//ds:Signature'))
9
+ Signature.new node
10
+ else
11
+ raise Xmldsign::NodeError, 'node ds:Signature is not found in document'
12
+ end
13
+ end
14
+
15
+ def signed
16
+ signature.sign
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,2 @@
1
+ class Xmldsign::Error < StandardError
2
+ end
@@ -0,0 +1,64 @@
1
+ module Xmldsign
2
+ class Signature < DelegateClass(XML::Node)
3
+ XML_C14N_1_0 = 0
4
+ XML_C14N_EXCLUSIVE_1_0 = 1
5
+ XML_C14N_1_1 = 2
6
+
7
+ def signed_info
8
+ SignedInfo.new find_first('.//ds:SignedInfo')
9
+ end
10
+
11
+ def c14n_signed_info
12
+ sign
13
+ doc = LibXML::XML::Document.new
14
+ doc.root = signed_info.copy(true)
15
+ doc.canonicalize mode: XML_C14N_EXCLUSIVE_1_0
16
+ end
17
+
18
+ def canonicalization_method
19
+ node = find_first('.//ds:CanonicalizationMethod')
20
+ Algorithms.factory node['Algorithm'], node
21
+ end
22
+
23
+ def digest_method
24
+ node = find_first('.//ds:DigestMethod')
25
+ Algorithms.factory node['Algorithm'], node
26
+ end
27
+
28
+ def transforms
29
+ signed_info.transforms
30
+ end
31
+
32
+ def sign
33
+ fill_digest!
34
+ clear_signature_value!
35
+ clear_certificate!
36
+ doc
37
+ end
38
+
39
+ def clear_signature_value!
40
+ if (node = find_first('.//ds:SignatureValue'))
41
+ node.content = ''
42
+ end
43
+ end
44
+
45
+ def clear_certificate!
46
+ if (node = find_first('.//ds:X509Certificate'))
47
+ node.content = ''
48
+ end
49
+ end
50
+
51
+ def fill_digest!
52
+ if (node = find_first('.//ds:DigestValue'))
53
+ node.content = calculate_digest
54
+ else
55
+ raise Xmldsign::NodeError, 'node ds:DigestValue is not found in document'
56
+ end
57
+ end
58
+
59
+ def calculate_digest
60
+ digest_method.execute transforms.execute
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,7 @@
1
+ module Xmldsign
2
+ class SignedInfo < DelegateClass(XML::Node)
3
+ def transforms
4
+ Transforms.new find_first('.//ds:Transforms')
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module Xmldsign
2
+ class Transforms < DelegateClass(XML::Node)
3
+ def execute(document=self.doc)
4
+ doc = LibXML::XML::Document.new
5
+ doc.root = document.root.copy(true)
6
+ algorithms.inject(doc) { |d, algorithm| algorithm.execute d }
7
+ end
8
+
9
+ def algorithms
10
+ find('.//ds:Transform').map { |t| factory(t['Algorithm'], t) }
11
+ end
12
+
13
+ def factory(algorithm, node)
14
+ Algorithms.factory(algorithm, node)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Xmldsign
2
+ VERSION = "0.1.0"
3
+ end
data/lib/xmldsign.rb ADDED
@@ -0,0 +1,21 @@
1
+ require "xmldsign/version"
2
+ require "xmldsign/error"
3
+ require "xmldsign/digests/gost"
4
+ require "libxml"
5
+ require "libxslt"
6
+ require "delegate"
7
+ require "base64"
8
+
9
+ module Xmldsign
10
+ include LibXML
11
+
12
+ class NodeError < Error
13
+ end
14
+
15
+ autoload :Algorithms, 'xmldsign/algorithms'
16
+ autoload :Document, 'xmldsign/document'
17
+ autoload :Signature, 'xmldsign/signature'
18
+ autoload :SignedInfo, 'xmldsign/signed_info'
19
+ autoload :Transforms, 'xmldsign/transforms'
20
+ end
21
+