nokogiri-xmlsec-me-harder 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 818ee85467c194244bf1d1edb85ef9517bf5b9ea
4
- data.tar.gz: 35efec57db945b9f1e4cd8ce68f46861f7d51753
3
+ metadata.gz: 4adbd4c650866b34094b2fa5e2dba632405ec1ad
4
+ data.tar.gz: fe55cb91ae8d76a9d0708e56b912f7d96e7432cc
5
5
  SHA512:
6
- metadata.gz: 83da2b119f79759178bd4de9680dfefad1d7152abc341c4f8eb25a1cf44311fcb0626c4de55a73c742c1e2b19e426059eff8de1293e2256bdd2643594abfd0e5
7
- data.tar.gz: f9e5ff73c6c7f25d60edb7bdd2b827cf202c81c2315c0aa9419397da03d387b4d977a8714706cf0e7c4967fd5297026fe112d712cacbf3bb23b507763635f2f8
6
+ metadata.gz: b944b6c83a4983e7ef565a3dad2607152c88575ab12e272c339b394b394c53155e02b932cc26cf06f485bf289589a9d395042450009f3e57b92aee45058910bc
7
+ data.tar.gz: 3d0f2c65bcbdd39a037f9cda8f62c13958570a915d5f7bf423afe63b34da4ed0c77842c604d8bc923d2914ea7a026a7f1f48df64b39a17e515e91510f248b572
data/README.md CHANGED
@@ -40,17 +40,17 @@ then returns itself.
40
40
  doc = Nokogiri::XML("<doc><greeting>Hello, World!</greeting></doc>")
41
41
 
42
42
  # Sign the document with a certificate, a key, and a key name
43
- doc.sign! certificate: 'certificate data',
43
+ doc.sign! cert: 'certificate data',
44
44
  key: 'private key data',
45
- name: 'private key name'
45
+ name: 'private key name',
46
+ digest_alg: 'sha256',
47
+ signature_alg: 'rsa-sha256'
46
48
 
47
- You only need one of `certificate` or `key`, but you can pass both. If you do,
48
- the certificate will be included as part of the signature, so that it can be
49
- later verified by certificate instead of by key.
49
+ If you pass `cert`, the certificate will be included as part of the signature,
50
+ so that it can be later verified by certificate instead of by key.
50
51
 
51
- The `name` is implicitly converted into a string. Thus it is effectively
52
- optional, since `nil` converts to `""`, and its value only matters if you plan
53
- to verify the signature with any of a set of keys, as in the following example:
52
+ `name` can be used to verify the signature with any of a set of keys, as in the
53
+ following example:
54
54
 
55
55
  ### Signature verification
56
56
 
@@ -73,11 +73,11 @@ same key, you can do it like so, effectively ignoring the `name` value:
73
73
  Finally, you can also verify with a certificate:
74
74
 
75
75
  # Verify the document's signature with a single certificate
76
- doc.verify_with certificate: 'certificate data'
76
+ doc.verify_with cert: 'certificate data'
77
77
 
78
78
  # Verify the document's signature with multiple certificates. Any one match
79
79
  # will pass verification.
80
- doc.verify_with certificates: [ 'cert1', 'cert2', 'cert3' ]
80
+ doc.verify_with certs: [ 'cert1', 'cert2', 'cert3' ]
81
81
 
82
82
  If the certificate has been installed to your system certificates, then you can
83
83
  verify signatures like so:
@@ -111,8 +111,9 @@ Following is a list of limitations and/or issues I know about, but have no
111
111
  immediate plan to resolve. This is probably because I haven't needed the
112
112
  functionality, and no one has sent a pull request. (Hint, hint!)
113
113
 
114
- - Currently, it is not possible to operate on individual XML nodes. The
114
+ - Currently, it is not possible to encrypt/decrypt individual XML nodes. The
115
115
  `nokogiri-xmlsec` operations must be performed on the entire document.
116
+ You _can_ sign an individual node.
116
117
 
117
118
  ## Contributing
118
119
 
@@ -15,8 +15,7 @@ void Init_Nokogiri_ext() {
15
15
  rb_cNokogiri_XML_Document = rb_const_get(Nokogiri_XML, rb_intern("Document"));
16
16
  rb_cNokogiri_XML_Node = rb_const_get(Nokogiri_XML, rb_intern("Node"));
17
17
 
18
- rb_define_method(rb_cNokogiri_XML_Document, "sign_with_key", sign_with_key, 1);
19
- rb_define_method(rb_cNokogiri_XML_Document, "sign_with_certificate", sign_with_certificate, 1);
18
+ rb_define_method(rb_cNokogiri_XML_Node, "sign!", sign, 1);
20
19
  rb_define_method(rb_cNokogiri_XML_Document, "verify_with_rsa_key", verify_signature_with_rsa_key, 1);
21
20
  rb_define_method(rb_cNokogiri_XML_Document, "verify_with_named_keys", verify_signature_with_named_keys, 1);
22
21
  rb_define_method(rb_cNokogiri_XML_Document, "verify_with_certificates", verify_signature_with_certificates, 1);
@@ -17,16 +17,17 @@
17
17
  // :name - [optional] String with name of the rsa key.
18
18
  // :uri - [optional] The URI attribute for the <Reference> node in the
19
19
  // signature.
20
- VALUE sign_with_certificate(VALUE self, VALUE rb_opts) {
20
+ VALUE sign(VALUE self, VALUE rb_opts) {
21
21
  VALUE rb_exception_result = Qnil;
22
22
  const char* exception_message = NULL;
23
23
 
24
24
  xmlDocPtr doc = NULL;
25
+ xmlNodePtr envelopeNode = NULL;
25
26
  xmlNodePtr signNode = NULL;
26
27
  xmlNodePtr refNode = NULL;
27
28
  xmlNodePtr keyInfoNode = NULL;
28
29
  xmlSecDSigCtxPtr dsigCtx = NULL;
29
- char *keyName = "";
30
+ char *keyName = NULL;
30
31
  char *certificate = NULL;
31
32
  char *rsaKey = NULL;
32
33
  char *refUri = NULL;
@@ -43,15 +44,17 @@ VALUE sign_with_certificate(VALUE self, VALUE rb_opts) {
43
44
  VALUE rb_key_name = rb_hash_aref(rb_opts, ID2SYM(rb_intern("name")));
44
45
 
45
46
  Check_Type(rb_rsa_key, T_STRING);
46
- Check_Type(rb_cert, T_STRING);
47
47
  Check_Type(rb_signature_alg, T_STRING);
48
48
  Check_Type(rb_digest_alg, T_STRING);
49
49
 
50
50
  rsaKey = RSTRING_PTR(rb_rsa_key);
51
51
  rsaKeyLength = RSTRING_LEN(rb_rsa_key);
52
- certificate = RSTRING_PTR(rb_cert);
53
- certificateLength = RSTRING_LEN(rb_cert);
54
52
 
53
+ if (!NIL_P(rb_cert)) {
54
+ Check_Type(rb_cert, T_STRING);
55
+ certificate = RSTRING_PTR(rb_cert);
56
+ certificateLength = RSTRING_LEN(rb_cert);
57
+ }
55
58
  if (!NIL_P(rb_key_name)) {
56
59
  Check_Type(rb_key_name, T_STRING);
57
60
  keyName = StringValueCStr(rb_key_name);
@@ -61,7 +64,6 @@ VALUE sign_with_certificate(VALUE self, VALUE rb_opts) {
61
64
  refUri = StringValueCStr(rb_uri);
62
65
  }
63
66
 
64
- Data_Get_Struct(self, xmlDoc, doc);
65
67
  xmlSecTransformId signature_algorithm = GetSignatureMethod(rb_signature_alg,
66
68
  &rb_exception_result, &exception_message);
67
69
  if (signature_algorithm == xmlSecTransformIdUnknown) {
@@ -69,6 +71,8 @@ VALUE sign_with_certificate(VALUE self, VALUE rb_opts) {
69
71
  goto done;
70
72
  }
71
73
 
74
+ Data_Get_Struct(self, xmlNode, envelopeNode);
75
+ doc = envelopeNode->doc;
72
76
  // create signature template for enveloped signature.
73
77
  signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
74
78
  signature_algorithm, NULL);
@@ -79,7 +83,7 @@ VALUE sign_with_certificate(VALUE self, VALUE rb_opts) {
79
83
  }
80
84
 
81
85
  // add <dsig:Signature/> node to the doc
82
- xmlAddChild(xmlDocGetRootElement(doc), signNode);
86
+ xmlAddChild(envelopeNode, signNode);
83
87
 
84
88
  // add reference
85
89
  xmlSecTransformId digest_algorithm = GetDigestMethod(rb_digest_alg,
@@ -109,18 +113,30 @@ VALUE sign_with_certificate(VALUE self, VALUE rb_opts) {
109
113
  goto done;
110
114
  }
111
115
 
112
- // add <dsig:KeyInfo/> and <dsig:X509Data/>
116
+ // add <dsig:KeyInfo/>
113
117
  keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
114
118
  if(keyInfoNode == NULL) {
115
119
  rb_exception_result = rb_eSigningError;
116
120
  exception_message = "failed to add key info";
117
121
  goto done;
118
122
  }
119
-
120
- if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) {
121
- rb_exception_result = rb_eSigningError;
122
- exception_message = "failed to add X509Data node";
123
- goto done;
123
+
124
+ if(certificate) {
125
+ // add <dsig:X509Data/>
126
+ if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) {
127
+ rb_exception_result = rb_eSigningError;
128
+ exception_message = "failed to add X509Data node";
129
+ goto done;
130
+ }
131
+ }
132
+
133
+ if(keyName) {
134
+ // add <dsig:KeyName/>
135
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
136
+ rb_exception_result = rb_eSigningError;
137
+ exception_message = "failed to add key name";
138
+ goto done;
139
+ }
124
140
  }
125
141
 
126
142
  // create signature context, we don't need keys manager in this example
@@ -144,21 +160,25 @@ VALUE sign_with_certificate(VALUE self, VALUE rb_opts) {
144
160
  goto done;
145
161
  }
146
162
 
147
- // load certificate and add to the key
148
- if(xmlSecCryptoAppKeyCertLoadMemory(dsigCtx->signKey,
149
- (xmlSecByte *)certificate,
150
- certificateLength,
151
- xmlSecKeyDataFormatPem) < 0) {
152
- rb_exception_result = rb_eSigningError;
153
- exception_message = "failed to load certificate";
154
- goto done;
163
+ if(keyName) {
164
+ // set key name
165
+ if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
166
+ rb_exception_result = rb_eSigningError;
167
+ exception_message = "failed to set key name";
168
+ goto done;
169
+ }
155
170
  }
156
171
 
157
- // set key name
158
- if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
159
- rb_exception_result = rb_eSigningError;
160
- exception_message = "failed to set key name";
161
- goto done;
172
+ if(certificate) {
173
+ // load certificate and add to the key
174
+ if(xmlSecCryptoAppKeyCertLoadMemory(dsigCtx->signKey,
175
+ (xmlSecByte *)certificate,
176
+ certificateLength,
177
+ xmlSecKeyDataFormatPem) < 0) {
178
+ rb_exception_result = rb_eSigningError;
179
+ exception_message = "failed to load certificate";
180
+ goto done;
181
+ }
162
182
  }
163
183
 
164
184
  // sign the template
@@ -174,6 +194,13 @@ done:
174
194
  }
175
195
 
176
196
  if(rb_exception_result != Qnil) {
197
+ // remove the signature node before raising an exception, so that
198
+ // the document is untouched
199
+ if (signNode != NULL) {
200
+ xmlUnlinkNode(signNode);
201
+ xmlFreeNode(signNode);
202
+ }
203
+
177
204
  if (hasXmlSecLastError()) {
178
205
  rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
179
206
  getXmlSecLastError());
@@ -22,8 +22,7 @@
22
22
  // TODO(awong): Support non-gcc and non-clang compilers.
23
23
  #define EXTENSION_EXPORT __attribute__((visibility("default")))
24
24
 
25
- VALUE sign_with_key(VALUE self, VALUE rb_opts);
26
- VALUE sign_with_certificate(VALUE self, VALUE rb_opts);
25
+ VALUE sign(VALUE self, VALUE rb_opts);
27
26
  VALUE verify_signature_with_rsa_key(VALUE self, VALUE rb_rsa_key);
28
27
  VALUE verify_signature_with_named_keys(VALUE self, VALUE rb_keys);
29
28
  VALUE verify_signature_with_certificates(VALUE self, VALUE rb_certs);
@@ -3,24 +3,8 @@ require 'nokogiri'
3
3
  require 'nokogiri_ext_xmlsec'
4
4
 
5
5
  class Nokogiri::XML::Document
6
- # Signs this document, and then returns it.
7
- #
8
- # Examples:
9
- #
10
- # doc.sign! key: 'rsa-private-key'
11
- # doc.sign! key: 'rsa-private-key', name: 'key-name'
12
- # doc.sign! cert: 'x509 certificate', key: 'cert private key'
13
- # doc.sign! cert: 'x509 certificate', key: 'cert private key',
14
- # name: 'key-name'
15
6
  def sign! opts
16
- if opts.has_key? :cert
17
- raise "need a private :key" unless opts[:key]
18
- sign_with_certificate opts
19
- elsif opts[:key]
20
- sign_with_key opts
21
- else
22
- raise "No private :key was given"
23
- end
7
+ root.sign! opts
24
8
  self
25
9
  end
26
10
 
@@ -1,3 +1,3 @@
1
1
  module Xmlsec
2
- VERSION = '0.9.1'
2
+ VERSION = '0.9.2'
3
3
  end
@@ -32,7 +32,6 @@ describe "signing and verifying signatures:" do
32
32
  describe 'signing a document with an RSA key and X509 certificate' do
33
33
  before do
34
34
  subject.sign! key: fixture('cert/server.key.decrypted'),
35
- name: 'test',
36
35
  cert: fixture('cert/server.crt'),
37
36
  signature_alg: 'rsa-sha256',
38
37
  digest_alg: 'sha256'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nokogiri-xmlsec-me-harder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Albert J. Wong
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-20 00:00:00.000000000 Z
11
+ date: 2015-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -139,8 +139,7 @@ files:
139
139
  - ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c
140
140
  - ext/nokogiri_ext_xmlsec/nokogiri_helpers_set_attribute_id.c
141
141
  - ext/nokogiri_ext_xmlsec/nokogiri_init.c
142
- - ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c
143
- - ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c
142
+ - ext/nokogiri_ext_xmlsec/nokogiri_sign.c
144
143
  - ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c
145
144
  - ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c
146
145
  - ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c
@@ -1,167 +0,0 @@
1
- #include "xmlsecrb.h"
2
-
3
- #include "options.h"
4
- #include "util.h"
5
-
6
- // Appends an xmlsig <dsig:Signature> node to document stored in |self|
7
- // with a signature based on the given bare rsa key and keyname.
8
- //
9
- // Expects a ruby hash for the signing arguments.
10
- // Hash parameters:
11
- // :key_name - String with name of the rsa key. May be the empty string.
12
- // :rsa_key - A PEM encoded rsa key for signing.
13
- // :signature_alg - Algorithm identified by the URL fragment. Supported algorithms
14
- // taken from http://www.w3.org/TR/xmldsig-core
15
- // :digest_alg - Algorithm identified by the URL fragment. Supported algorithms
16
- // taken from http://www.w3.org/TR/xmldsig-core
17
- // :ref_uri - [optional] The URI attribute for the <Reference> node in the
18
- // signature.
19
- VALUE sign_with_key(VALUE self, VALUE rb_opts) {
20
- VALUE rb_exception_result = Qnil;
21
- const char* exception_message = NULL;
22
-
23
- xmlDocPtr doc = NULL;
24
- xmlNodePtr signNode = NULL;
25
- xmlNodePtr refNode = NULL;
26
- xmlNodePtr keyInfoNode = NULL;
27
- xmlSecDSigCtxPtr dsigCtx = NULL;
28
- char *keyName = NULL;
29
- char *rsaKey = NULL;
30
- char *refUri = NULL;
31
- unsigned int rsaKeyLength = 0;
32
-
33
- resetXmlSecError();
34
-
35
- VALUE rb_key_name = rb_hash_aref(rb_opts, ID2SYM(rb_intern("name")));
36
- VALUE rb_rsa_key = rb_hash_aref(rb_opts, ID2SYM(rb_intern("key")));
37
- VALUE rb_signature_alg = rb_hash_aref(rb_opts, ID2SYM(rb_intern("signature_alg")));
38
- VALUE rb_digest_alg = rb_hash_aref(rb_opts, ID2SYM(rb_intern("digest_alg")));
39
- VALUE rb_uri = rb_hash_aref(rb_opts, ID2SYM(rb_intern("uri")));
40
-
41
- Check_Type(rb_rsa_key, T_STRING);
42
- Check_Type(rb_key_name, T_STRING);
43
- Check_Type(rb_signature_alg, T_STRING);
44
- Check_Type(rb_digest_alg, T_STRING);
45
-
46
- rsaKey = RSTRING_PTR(rb_rsa_key);
47
- rsaKeyLength = RSTRING_LEN(rb_rsa_key);
48
- keyName = StringValueCStr(rb_key_name);
49
-
50
- if (!NIL_P(rb_uri)) {
51
- Check_Type(rb_uri, T_STRING);
52
- refUri = StringValueCStr(rb_uri);
53
- }
54
-
55
- Data_Get_Struct(self, xmlDoc, doc);
56
- xmlSecTransformId signature_algorithm = GetSignatureMethod(rb_signature_alg,
57
- &rb_exception_result, &exception_message);
58
- if (signature_algorithm == xmlSecTransformIdUnknown) {
59
- // Propagate exception.
60
- goto done;
61
- }
62
-
63
- // create signature template for enveloped signature
64
- signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
65
- signature_algorithm, NULL);
66
- if (signNode == NULL) {
67
- rb_exception_result = rb_eSigningError;
68
- exception_message = "failed to create signature template";
69
- goto done;
70
- }
71
-
72
- // add <dsig:Signature/> node to the doc
73
- xmlAddChild(xmlDocGetRootElement(doc), signNode);
74
-
75
- // add reference
76
- xmlSecTransformId digest_algorithm = GetDigestMethod(rb_digest_alg,
77
- &rb_exception_result, &exception_message);
78
- if (digest_algorithm == xmlSecTransformIdUnknown) {
79
- // Propagate exception.
80
- goto done;
81
- }
82
- refNode = xmlSecTmplSignatureAddReference(signNode, digest_algorithm,
83
- NULL, (const xmlChar *)refUri, NULL);
84
- if(refNode == NULL) {
85
- rb_exception_result = rb_eSigningError;
86
- exception_message = "failed to add reference to signature template";
87
- goto done;
88
- }
89
-
90
- // add enveloped transform
91
- if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
92
- rb_exception_result = rb_eSigningError;
93
- exception_message = "failed to add enveloped transform to reference";
94
- goto done;
95
- }
96
-
97
- if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformExclC14NId) == NULL) {
98
- rb_exception_result = rb_eSigningError;
99
- exception_message = "failed to add canonicalization transform to reference";
100
- goto done;
101
- }
102
-
103
- // add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed
104
- // document
105
- keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
106
- if(keyInfoNode == NULL) {
107
- rb_exception_result = rb_eSigningError;
108
- exception_message = "failed to add key info";
109
- goto done;
110
- }
111
- if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
112
- rb_exception_result = rb_eSigningError;
113
- exception_message = "failed to add key name";
114
- goto done;
115
- }
116
-
117
- // create signature context, we don't need keys manager in this example
118
- dsigCtx = createDSigContext(NULL);
119
- if(dsigCtx == NULL) {
120
- rb_exception_result = rb_eSigningError;
121
- exception_message = "failed to create signature context";
122
- goto done;
123
- }
124
-
125
- // load private key, assuming that there is no password
126
- dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
127
- rsaKeyLength,
128
- xmlSecKeyDataFormatPem,
129
- NULL, // password
130
- NULL,
131
- NULL);
132
- if(dsigCtx->signKey == NULL) {
133
- rb_exception_result = rb_eSigningError;
134
- exception_message = "failed to load private pem key";
135
- goto done;
136
- }
137
-
138
- // set key name
139
- if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
140
- rb_exception_result = rb_eSigningError;
141
- exception_message = "failed to set key name";
142
- goto done;
143
- }
144
-
145
- // sign the template
146
- if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
147
- rb_exception_result = rb_eSigningError;
148
- exception_message = "signature failed";
149
- goto done;
150
- }
151
-
152
- done:
153
- if(dsigCtx != NULL) {
154
- xmlSecDSigCtxDestroy(dsigCtx);
155
- }
156
-
157
- if(rb_exception_result != Qnil) {
158
- if (hasXmlSecLastError()) {
159
- rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
160
- getXmlSecLastError());
161
- } else {
162
- rb_raise(rb_exception_result, "%s", exception_message);
163
- }
164
- }
165
-
166
- return Qnil;
167
- }