nokogiri-xmlsec-me-harder 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- }