nokogiri-xmlsec 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +121 -0
- data/Rakefile +30 -0
- data/ext/nokogiri_ext_xmlsec/extconf.rb +20 -0
- data/ext/nokogiri_ext_xmlsec/init.c +46 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_decrypt_with_key.c +124 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c +182 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +29 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c +104 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c +95 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c +96 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c +106 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c +56 -0
- data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
- data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +38 -0
- data/lib/nokogiri-xmlsec.rb +1 -0
- data/lib/xmlsec.rb +110 -0
- data/lib/xmlsec/version.rb +3 -0
- data/nokogiri-xmlsec.gemspec +36 -0
- data/spec/fixtures/cert/server.crt +14 -0
- data/spec/fixtures/cert/server.csr +11 -0
- data/spec/fixtures/cert/server.key.decrypted +15 -0
- data/spec/fixtures/cert/server.key.encrypted +18 -0
- data/spec/fixtures/rsa.pem +15 -0
- data/spec/fixtures/rsa.pub +6 -0
- data/spec/fixtures/sign2-doc.xml +6 -0
- data/spec/fixtures/sign2-result.xml +24 -0
- data/spec/fixtures/sign3-result.xml +37 -0
- data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +28 -0
- data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +70 -0
- data/spec/spec_helper.rb +10 -0
- metadata +196 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
#include "xmlsecrb.h"
|
2
|
+
|
3
|
+
VALUE rb_cNokogiri_XML_Document = T_NIL;
|
4
|
+
VALUE rb_eSigningError = T_NIL;
|
5
|
+
VALUE rb_eVerificationError = T_NIL;
|
6
|
+
VALUE rb_eKeystoreError = T_NIL;
|
7
|
+
VALUE rb_eEncryptionError = T_NIL;
|
8
|
+
VALUE rb_eDecryptionError = T_NIL;
|
9
|
+
|
10
|
+
void Init_Nokogiri_ext() {
|
11
|
+
VALUE XMLSec = rb_define_module("XMLSec");
|
12
|
+
VALUE Nokogiri = rb_define_module("Nokogiri");
|
13
|
+
VALUE Nokogiri_XML = rb_define_module_under(Nokogiri, "XML");
|
14
|
+
rb_cNokogiri_XML_Document = rb_const_get(Nokogiri_XML, rb_intern("Document"));
|
15
|
+
|
16
|
+
rb_define_method(rb_cNokogiri_XML_Document, "sign_with_key", sign_with_key, 2);
|
17
|
+
rb_define_method(rb_cNokogiri_XML_Document, "sign_with_certificate", sign_with_certificate, 3);
|
18
|
+
rb_define_method(rb_cNokogiri_XML_Document, "verify_with_rsa_key", verify_signature_with_rsa_key, 1);
|
19
|
+
rb_define_method(rb_cNokogiri_XML_Document, "verify_with_named_keys", verify_signature_with_named_keys, 1);
|
20
|
+
rb_define_method(rb_cNokogiri_XML_Document, "verify_with_certificates", verify_signature_with_certificates, 1);
|
21
|
+
rb_define_method(rb_cNokogiri_XML_Document, "encrypt_with_key", encrypt_with_key, 2);
|
22
|
+
rb_define_method(rb_cNokogiri_XML_Document, "decrypt_with_key", decrypt_with_key, 2);
|
23
|
+
|
24
|
+
rb_eSigningError = rb_define_class_under(XMLSec, "SigningError", rb_eRuntimeError);
|
25
|
+
rb_eVerificationError = rb_define_class_under(XMLSec, "VerificationError", rb_eRuntimeError);
|
26
|
+
rb_eKeystoreError = rb_define_class_under(XMLSec, "KeystoreError", rb_eRuntimeError);
|
27
|
+
rb_eEncryptionError = rb_define_class_under(XMLSec, "EncryptionError", rb_eRuntimeError);
|
28
|
+
rb_eDecryptionError = rb_define_class_under(XMLSec, "DecryptionError", rb_eRuntimeError);
|
29
|
+
}
|
@@ -0,0 +1,104 @@
|
|
1
|
+
#include "xmlsecrb.h"
|
2
|
+
|
3
|
+
VALUE sign_with_certificate(VALUE self, VALUE rb_key_name, VALUE rb_rsa_key, VALUE rb_cert) {
|
4
|
+
xmlDocPtr doc;
|
5
|
+
xmlNodePtr signNode = NULL;
|
6
|
+
xmlNodePtr refNode = NULL;
|
7
|
+
xmlNodePtr keyInfoNode = NULL;
|
8
|
+
xmlSecDSigCtxPtr dsigCtx = NULL;
|
9
|
+
char *keyName;
|
10
|
+
char *certificate;
|
11
|
+
char *rsaKey;
|
12
|
+
unsigned int rsaKeyLength, certificateLength;
|
13
|
+
|
14
|
+
Data_Get_Struct(self, xmlDoc, doc);
|
15
|
+
rsaKey = RSTRING_PTR(rb_rsa_key);
|
16
|
+
rsaKeyLength = RSTRING_LEN(rb_rsa_key);
|
17
|
+
keyName = RSTRING_PTR(rb_key_name);
|
18
|
+
certificate = RSTRING_PTR(rb_cert);
|
19
|
+
certificateLength = RSTRING_LEN(rb_cert);
|
20
|
+
|
21
|
+
// create signature template for RSA-SHA1 enveloped signature
|
22
|
+
signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
|
23
|
+
xmlSecTransformRsaSha1Id, NULL);
|
24
|
+
if (signNode == NULL) {
|
25
|
+
rb_raise(rb_eSigningError, "failed to create signature template");
|
26
|
+
goto done;
|
27
|
+
}
|
28
|
+
|
29
|
+
// add <dsig:Signature/> node to the doc
|
30
|
+
xmlAddChild(xmlDocGetRootElement(doc), signNode);
|
31
|
+
|
32
|
+
// add reference
|
33
|
+
refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id,
|
34
|
+
NULL, NULL, NULL);
|
35
|
+
if(refNode == NULL) {
|
36
|
+
rb_raise(rb_eSigningError, "failed to add reference to signature template");
|
37
|
+
goto done;
|
38
|
+
}
|
39
|
+
|
40
|
+
// add enveloped transform
|
41
|
+
if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
|
42
|
+
rb_raise(rb_eSigningError, "failed to add enveloped transform to reference");
|
43
|
+
goto done;
|
44
|
+
}
|
45
|
+
|
46
|
+
// add <dsig:KeyInfo/> and <dsig:X509Data/>
|
47
|
+
keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
|
48
|
+
if(keyInfoNode == NULL) {
|
49
|
+
rb_raise(rb_eSigningError, "failed to add key info");
|
50
|
+
goto done;
|
51
|
+
}
|
52
|
+
|
53
|
+
if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) {
|
54
|
+
rb_raise(rb_eSigningError, "failed to add X509Data node");
|
55
|
+
goto done;
|
56
|
+
}
|
57
|
+
|
58
|
+
// create signature context, we don't need keys manager in this example
|
59
|
+
dsigCtx = xmlSecDSigCtxCreate(NULL);
|
60
|
+
if(dsigCtx == NULL) {
|
61
|
+
rb_raise(rb_eSigningError, "failed to create signature context");
|
62
|
+
goto done;
|
63
|
+
}
|
64
|
+
|
65
|
+
// load private key, assuming that there is not password
|
66
|
+
dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
|
67
|
+
rsaKeyLength,
|
68
|
+
xmlSecKeyDataFormatPem,
|
69
|
+
NULL, // password
|
70
|
+
NULL,
|
71
|
+
NULL);
|
72
|
+
if(dsigCtx->signKey == NULL) {
|
73
|
+
rb_raise(rb_eSigningError, "failed to load private key");
|
74
|
+
goto done;
|
75
|
+
}
|
76
|
+
|
77
|
+
// load certificate and add to the key
|
78
|
+
if(xmlSecCryptoAppKeyCertLoadMemory(dsigCtx->signKey,
|
79
|
+
(xmlSecByte *)certificate,
|
80
|
+
certificateLength,
|
81
|
+
xmlSecKeyDataFormatPem) < 0) {
|
82
|
+
rb_raise(rb_eSigningError, "failed to load certificate");
|
83
|
+
goto done;
|
84
|
+
}
|
85
|
+
|
86
|
+
// set key name
|
87
|
+
if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
|
88
|
+
rb_raise(rb_eSigningError, "failed to set key name");
|
89
|
+
goto done;
|
90
|
+
}
|
91
|
+
|
92
|
+
// sign the template
|
93
|
+
if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
|
94
|
+
rb_raise(rb_eSigningError, "signature failed");
|
95
|
+
goto done;
|
96
|
+
}
|
97
|
+
|
98
|
+
done:
|
99
|
+
if(dsigCtx != NULL) {
|
100
|
+
xmlSecDSigCtxDestroy(dsigCtx);
|
101
|
+
}
|
102
|
+
|
103
|
+
return T_NIL;
|
104
|
+
}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
#include "xmlsecrb.h"
|
2
|
+
|
3
|
+
// TODO the signature context probably should be a ruby instance variable
|
4
|
+
// and separate object, instead of being allocated/freed in each method.
|
5
|
+
|
6
|
+
VALUE sign_with_key(VALUE self, VALUE rb_key_name, VALUE rb_rsa_key) {
|
7
|
+
xmlDocPtr doc;
|
8
|
+
xmlNodePtr signNode = NULL;
|
9
|
+
xmlNodePtr refNode = NULL;
|
10
|
+
xmlNodePtr keyInfoNode = NULL;
|
11
|
+
xmlSecDSigCtxPtr dsigCtx = NULL;
|
12
|
+
char *keyName;
|
13
|
+
char *rsaKey;
|
14
|
+
unsigned int rsaKeyLength;
|
15
|
+
|
16
|
+
Data_Get_Struct(self, xmlDoc, doc);
|
17
|
+
rsaKey = RSTRING_PTR(rb_rsa_key);
|
18
|
+
rsaKeyLength = RSTRING_LEN(rb_rsa_key);
|
19
|
+
keyName = RSTRING_PTR(rb_key_name);
|
20
|
+
|
21
|
+
// create signature template for RSA-SHA1 enveloped signature
|
22
|
+
signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
|
23
|
+
xmlSecTransformRsaSha1Id, NULL);
|
24
|
+
if (signNode == NULL) {
|
25
|
+
rb_raise(rb_eSigningError, "failed to create signature template");
|
26
|
+
goto done;
|
27
|
+
}
|
28
|
+
|
29
|
+
// add <dsig:Signature/> node to the doc
|
30
|
+
xmlAddChild(xmlDocGetRootElement(doc), signNode);
|
31
|
+
|
32
|
+
// add reference
|
33
|
+
refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id,
|
34
|
+
NULL, NULL, NULL);
|
35
|
+
if(refNode == NULL) {
|
36
|
+
rb_raise(rb_eSigningError, "failed to add reference to signature template");
|
37
|
+
goto done;
|
38
|
+
}
|
39
|
+
|
40
|
+
// add enveloped transform
|
41
|
+
if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
|
42
|
+
rb_raise(rb_eSigningError, "failed to add enveloped transform to reference");
|
43
|
+
goto done;
|
44
|
+
}
|
45
|
+
|
46
|
+
// add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed
|
47
|
+
// document
|
48
|
+
keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
|
49
|
+
if(keyInfoNode == NULL) {
|
50
|
+
rb_raise(rb_eSigningError, "failed to add key info");
|
51
|
+
goto done;
|
52
|
+
}
|
53
|
+
if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
|
54
|
+
rb_raise(rb_eSigningError, "failed to add key name");
|
55
|
+
goto done;
|
56
|
+
}
|
57
|
+
|
58
|
+
// create signature context, we don't need keys manager in this example
|
59
|
+
dsigCtx = xmlSecDSigCtxCreate(NULL);
|
60
|
+
if(dsigCtx == NULL) {
|
61
|
+
rb_raise(rb_eSigningError, "failed to create signature context");
|
62
|
+
goto done;
|
63
|
+
}
|
64
|
+
|
65
|
+
// load private key, assuming that there is no password
|
66
|
+
dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
|
67
|
+
rsaKeyLength,
|
68
|
+
xmlSecKeyDataFormatPem,
|
69
|
+
NULL, // password
|
70
|
+
NULL,
|
71
|
+
NULL);
|
72
|
+
if(dsigCtx->signKey == NULL) {
|
73
|
+
rb_raise(rb_eSigningError, "failed to load private pem key");
|
74
|
+
goto done;
|
75
|
+
}
|
76
|
+
|
77
|
+
// set key name
|
78
|
+
if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
|
79
|
+
rb_raise(rb_eSigningError, "failed to set key name");
|
80
|
+
goto done;
|
81
|
+
}
|
82
|
+
|
83
|
+
// sign the template
|
84
|
+
if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
|
85
|
+
rb_raise(rb_eSigningError, "signature failed");
|
86
|
+
goto done;
|
87
|
+
}
|
88
|
+
|
89
|
+
done:
|
90
|
+
if(dsigCtx != NULL) {
|
91
|
+
xmlSecDSigCtxDestroy(dsigCtx);
|
92
|
+
}
|
93
|
+
|
94
|
+
return T_NIL;
|
95
|
+
}
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#include "xmlsecrb.h"
|
2
|
+
|
3
|
+
static xmlSecKeysMngrPtr getKeyManager(VALUE rb_certs) {
|
4
|
+
int i, numCerts = RARRAY_LEN(rb_certs);
|
5
|
+
xmlSecKeysMngrPtr keyManager = xmlSecKeysMngrCreate();
|
6
|
+
VALUE rb_cert;
|
7
|
+
char *cert;
|
8
|
+
unsigned int certLength;
|
9
|
+
int numSuccessful = 0;
|
10
|
+
|
11
|
+
if (keyManager == NULL) return NULL;
|
12
|
+
|
13
|
+
if (xmlSecCryptoAppDefaultKeysMngrInit(keyManager) < 0) {
|
14
|
+
rb_raise(rb_eKeystoreError, "could not initialize key manager");
|
15
|
+
xmlSecKeysMngrDestroy(keyManager);
|
16
|
+
return NULL;
|
17
|
+
}
|
18
|
+
|
19
|
+
for (i = 0; i < numCerts; i++) {
|
20
|
+
rb_cert = RARRAY_PTR(rb_certs)[i];
|
21
|
+
Check_Type(rb_cert, T_STRING);
|
22
|
+
cert = RSTRING_PTR(rb_cert);
|
23
|
+
certLength = RSTRING_LEN(rb_cert);
|
24
|
+
|
25
|
+
if(xmlSecCryptoAppKeysMngrCertLoadMemory(keyManager,
|
26
|
+
(xmlSecByte *)cert,
|
27
|
+
certLength,
|
28
|
+
xmlSecKeyDataFormatPem,
|
29
|
+
xmlSecKeyDataTypeTrusted) < 0) {
|
30
|
+
rb_warn("failed to load certificate at index %d", i);
|
31
|
+
} else {
|
32
|
+
numSuccessful++;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
// note, numCerts could be zero, meaning that we should use system SSL certs
|
37
|
+
if (numSuccessful == 0 && numCerts != 0) {
|
38
|
+
rb_raise(rb_eKeystoreError, "Could not load any of the specified certificates for signature verification");
|
39
|
+
xmlSecKeysMngrDestroy(keyManager);
|
40
|
+
return NULL;
|
41
|
+
}
|
42
|
+
|
43
|
+
return keyManager;
|
44
|
+
}
|
45
|
+
|
46
|
+
VALUE verify_signature_with_certificates(VALUE self, VALUE rb_certs) {
|
47
|
+
xmlDocPtr doc;
|
48
|
+
xmlNodePtr node = NULL;
|
49
|
+
xmlSecDSigCtxPtr dsigCtx = NULL;
|
50
|
+
xmlSecKeysMngrPtr keyManager = NULL;
|
51
|
+
VALUE result = Qfalse;
|
52
|
+
|
53
|
+
Check_Type(rb_certs, T_ARRAY);
|
54
|
+
Data_Get_Struct(self, xmlDoc, doc);
|
55
|
+
|
56
|
+
// find start node
|
57
|
+
node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
|
58
|
+
if(node == NULL) {
|
59
|
+
rb_raise(rb_eVerificationError, "start node not found");
|
60
|
+
goto done;
|
61
|
+
}
|
62
|
+
|
63
|
+
keyManager = getKeyManager(rb_certs);
|
64
|
+
if (keyManager == NULL) {
|
65
|
+
rb_raise(rb_eKeystoreError, "failed to create key manager");
|
66
|
+
goto done;
|
67
|
+
}
|
68
|
+
|
69
|
+
// create signature context, we don't need keys manager in this example
|
70
|
+
dsigCtx = xmlSecDSigCtxCreate(keyManager);
|
71
|
+
if(dsigCtx == NULL) {
|
72
|
+
rb_raise(rb_eVerificationError, "failed to create signature context");
|
73
|
+
goto done;
|
74
|
+
}
|
75
|
+
|
76
|
+
// verify signature
|
77
|
+
if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
|
78
|
+
rb_raise(rb_eVerificationError, "signature could not be verified");
|
79
|
+
goto done;
|
80
|
+
}
|
81
|
+
|
82
|
+
if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
|
83
|
+
result = Qtrue;
|
84
|
+
}
|
85
|
+
|
86
|
+
done:
|
87
|
+
if(dsigCtx != NULL) {
|
88
|
+
xmlSecDSigCtxDestroy(dsigCtx);
|
89
|
+
}
|
90
|
+
|
91
|
+
if (keyManager != NULL) {
|
92
|
+
xmlSecKeysMngrDestroy(keyManager);
|
93
|
+
}
|
94
|
+
|
95
|
+
return result;
|
96
|
+
}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
#include "xmlsecrb.h"
|
2
|
+
|
3
|
+
static int addRubyKeyToManager(VALUE rb_key, VALUE rb_value, VALUE rb_manager) {
|
4
|
+
xmlSecKeysMngrPtr keyManager = (xmlSecKeysMngrPtr)rb_manager;
|
5
|
+
char *keyName, *keyData;
|
6
|
+
unsigned int keyDataLength;
|
7
|
+
xmlSecKeyPtr key;
|
8
|
+
|
9
|
+
Check_Type(rb_key, T_STRING);
|
10
|
+
Check_Type(rb_value, T_STRING);
|
11
|
+
keyName = RSTRING_PTR(rb_key);
|
12
|
+
keyData = RSTRING_PTR(rb_value);
|
13
|
+
keyDataLength = RSTRING_LEN(rb_value);
|
14
|
+
|
15
|
+
// load key
|
16
|
+
key = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)keyData,
|
17
|
+
keyDataLength,
|
18
|
+
xmlSecKeyDataFormatPem,
|
19
|
+
NULL, // password
|
20
|
+
NULL, NULL);
|
21
|
+
if (key == NULL) {
|
22
|
+
rb_warn("failed to load '%s' public or private pem key", keyName);
|
23
|
+
return ST_CONTINUE;
|
24
|
+
}
|
25
|
+
|
26
|
+
// set key name
|
27
|
+
if (xmlSecKeySetName(key, BAD_CAST keyName) < 0) {
|
28
|
+
rb_warn("failed to set key name for key '%s'", keyName);
|
29
|
+
return ST_CONTINUE;
|
30
|
+
}
|
31
|
+
|
32
|
+
// add key to key manager; from now on the manager is responsible for
|
33
|
+
// destroying the key
|
34
|
+
if (xmlSecCryptoAppDefaultKeysMngrAdoptKey(keyManager, key) < 0) {
|
35
|
+
rb_warn("failed to add key '%s' to key manager", keyName);
|
36
|
+
return ST_CONTINUE;
|
37
|
+
}
|
38
|
+
|
39
|
+
return ST_CONTINUE;
|
40
|
+
}
|
41
|
+
|
42
|
+
static xmlSecKeysMngrPtr getKeyManager(VALUE rb_hash) {
|
43
|
+
xmlSecKeysMngrPtr keyManager = xmlSecKeysMngrCreate();
|
44
|
+
if (keyManager == NULL) return NULL;
|
45
|
+
if (xmlSecCryptoAppDefaultKeysMngrInit(keyManager) < 0) {
|
46
|
+
rb_raise(rb_eKeystoreError, "could not initialize key manager");
|
47
|
+
xmlSecKeysMngrDestroy(keyManager);
|
48
|
+
return NULL;
|
49
|
+
}
|
50
|
+
|
51
|
+
rb_hash_foreach(rb_hash, addRubyKeyToManager, (VALUE)keyManager);
|
52
|
+
|
53
|
+
return keyManager;
|
54
|
+
}
|
55
|
+
|
56
|
+
VALUE verify_signature_with_named_keys(VALUE self, VALUE rb_hash) {
|
57
|
+
xmlDocPtr doc;
|
58
|
+
xmlNodePtr node = NULL;
|
59
|
+
xmlSecDSigCtxPtr dsigCtx = NULL;
|
60
|
+
xmlSecKeysMngrPtr keyManager = NULL;
|
61
|
+
VALUE result = Qfalse;
|
62
|
+
|
63
|
+
Check_Type(rb_hash, T_HASH);
|
64
|
+
Data_Get_Struct(self, xmlDoc, doc);
|
65
|
+
|
66
|
+
// find start node
|
67
|
+
node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
|
68
|
+
if(node == NULL) {
|
69
|
+
rb_raise(rb_eVerificationError, "start node not found");
|
70
|
+
goto done;
|
71
|
+
}
|
72
|
+
|
73
|
+
keyManager = getKeyManager(rb_hash);
|
74
|
+
if (keyManager == NULL) {
|
75
|
+
rb_raise(rb_eKeystoreError, "failed to create key manager");
|
76
|
+
goto done;
|
77
|
+
}
|
78
|
+
|
79
|
+
// create signature context, we don't need keys manager in this example
|
80
|
+
dsigCtx = xmlSecDSigCtxCreate(keyManager);
|
81
|
+
if(dsigCtx == NULL) {
|
82
|
+
rb_raise(rb_eVerificationError, "failed to create signature context");
|
83
|
+
goto done;
|
84
|
+
}
|
85
|
+
|
86
|
+
// verify signature
|
87
|
+
if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
|
88
|
+
rb_raise(rb_eVerificationError, "signature could not be verified");
|
89
|
+
goto done;
|
90
|
+
}
|
91
|
+
|
92
|
+
if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
|
93
|
+
result = Qtrue;
|
94
|
+
}
|
95
|
+
|
96
|
+
done:
|
97
|
+
if(dsigCtx != NULL) {
|
98
|
+
xmlSecDSigCtxDestroy(dsigCtx);
|
99
|
+
}
|
100
|
+
|
101
|
+
if (keyManager != NULL) {
|
102
|
+
xmlSecKeysMngrDestroy(keyManager);
|
103
|
+
}
|
104
|
+
|
105
|
+
return result;
|
106
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#include "xmlsecrb.h"
|
2
|
+
|
3
|
+
VALUE verify_signature_with_rsa_key(VALUE self, VALUE rb_rsa_key) {
|
4
|
+
xmlDocPtr doc;
|
5
|
+
xmlNodePtr node = NULL;
|
6
|
+
xmlSecDSigCtxPtr dsigCtx = NULL;
|
7
|
+
char *rsaKey;
|
8
|
+
unsigned int rsaKeyLength;
|
9
|
+
VALUE result = Qfalse;
|
10
|
+
|
11
|
+
Data_Get_Struct(self, xmlDoc, doc);
|
12
|
+
rsaKey = RSTRING_PTR(rb_rsa_key);
|
13
|
+
rsaKeyLength = RSTRING_LEN(rb_rsa_key);
|
14
|
+
|
15
|
+
// find start node
|
16
|
+
node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
|
17
|
+
if(node == NULL) {
|
18
|
+
rb_raise(rb_eVerificationError, "start node not found");
|
19
|
+
goto done;
|
20
|
+
}
|
21
|
+
|
22
|
+
// create signature context, we don't need keys manager in this example
|
23
|
+
dsigCtx = xmlSecDSigCtxCreate(NULL);
|
24
|
+
if(dsigCtx == NULL) {
|
25
|
+
rb_raise(rb_eVerificationError, "failed to create signature context");
|
26
|
+
goto done;
|
27
|
+
}
|
28
|
+
|
29
|
+
// load public key
|
30
|
+
dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
|
31
|
+
rsaKeyLength,
|
32
|
+
xmlSecKeyDataFormatPem,
|
33
|
+
NULL, // password
|
34
|
+
NULL, NULL);
|
35
|
+
if(dsigCtx->signKey == NULL) {
|
36
|
+
rb_raise(rb_eVerificationError, "failed to load public pem key");
|
37
|
+
goto done;
|
38
|
+
}
|
39
|
+
|
40
|
+
// verify signature
|
41
|
+
if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
|
42
|
+
rb_raise(rb_eVerificationError, "signature could not be verified");
|
43
|
+
goto done;
|
44
|
+
}
|
45
|
+
|
46
|
+
if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
|
47
|
+
result = Qtrue;
|
48
|
+
}
|
49
|
+
|
50
|
+
done:
|
51
|
+
if(dsigCtx != NULL) {
|
52
|
+
xmlSecDSigCtxDestroy(dsigCtx);
|
53
|
+
}
|
54
|
+
|
55
|
+
return result;
|
56
|
+
}
|