From: Scott Cantor Date: Wed, 15 Apr 2009 22:00:08 +0000 (+0000) Subject: Add helpers to encode keys into DER. X-Git-Tag: 1.2.0~19 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-xmltooling.git;a=commitdiff_plain;h=18296076c28faadea55aec9384967574bb485b99 Add helpers to encode keys into DER. --- diff --git a/xmltooling/security/SecurityHelper.h b/xmltooling/security/SecurityHelper.h index f2a8839..b62bdf5 100644 --- a/xmltooling/security/SecurityHelper.h +++ b/xmltooling/security/SecurityHelper.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Internet2 + * Copyright 2001-2009 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -124,6 +124,22 @@ namespace xmltooling { * @return true iff the keys match */ static bool matches(const XSECCryptoKey* key1, const XSECCryptoKey* key2); + + /** + * Returns the base64-encoded DER encoding of a public key in SubjectPublicKeyInfo format. + * + * @param key the key to encode + * @return the base64 encoded key value + */ + static std::string getDEREncoding(const XSECCryptoKey* key); + + /** + * Returns the base64-encoded DER encoding of a certifiate's public key in SubjectPublicKeyInfo format. + * + * @param cert the certificate's key to encode + * @return the base64 encoded key value + */ + static std::string getDEREncoding(const XSECCryptoX509* cert); }; }; diff --git a/xmltooling/security/impl/SecurityHelper.cpp b/xmltooling/security/impl/SecurityHelper.cpp index 5de29c7..0ee81ab 100644 --- a/xmltooling/security/impl/SecurityHelper.cpp +++ b/xmltooling/security/impl/SecurityHelper.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Internet2 + * Copyright 2001-2009 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -482,3 +482,73 @@ bool SecurityHelper::matches(const XSECCryptoKey* key1, const XSECCryptoKey* key Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("unsupported key type for comparison"); return false; } + +string SecurityHelper::getDEREncoding(const XSECCryptoKey* key) +{ + string ret; + + if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { + Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("encoding of non-OpenSSL keys not supported"); + return ret; + } + + if (key->getKeyType() == XSECCryptoKey::KEY_RSA_PUBLIC || key->getKeyType() == XSECCryptoKey::KEY_RSA_PAIR) { + const RSA* rsa = static_cast(key)->getOpenSSLRSA(); + BIO* base64 = BIO_new(BIO_f_base64()); + BIO_set_flags(base64, BIO_FLAGS_BASE64_NO_NL); + BIO* mem = BIO_new(BIO_s_mem()); + BIO_push(base64, mem); + i2d_RSA_PUBKEY_bio(base64, const_cast(rsa)); + BIO_flush(base64); + BUF_MEM* bptr=NULL; + BIO_get_mem_ptr(base64, &bptr); + if (bptr && bptr->length > 0) + ret.append(bptr->data, bptr->length); + BIO_free_all(base64); + } + else if (key->getKeyType() == XSECCryptoKey::KEY_DSA_PUBLIC || key->getKeyType() == XSECCryptoKey::KEY_DSA_PAIR) { + const DSA* dsa = static_cast(key)->getOpenSSLDSA(); + BIO* base64 = BIO_new(BIO_f_base64()); + BIO_set_flags(base64, BIO_FLAGS_BASE64_NO_NL); + BIO* mem = BIO_new(BIO_s_mem()); + BIO_push(base64, mem); + i2d_DSA_PUBKEY_bio(base64, const_cast(dsa)); + BIO_flush(base64); + BUF_MEM* bptr=NULL; + BIO_get_mem_ptr(base64, &bptr); + if (bptr && bptr->length > 0) + ret.append(bptr->data, bptr->length); + BIO_free_all(base64); + } + else { + Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("encoding of non-RSA/DSA public keys not supported"); + } + return ret; +} + +string SecurityHelper::getDEREncoding(const XSECCryptoX509* cert) +{ + string ret; + + if (cert->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { + Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("encoding of non-OpenSSL keys not supported"); + return ret; + } + + const X509* x = static_cast(cert)->getOpenSSLX509(); + EVP_PKEY* key = X509_get_pubkey(const_cast(x)); + + BIO* base64 = BIO_new(BIO_f_base64()); + BIO_set_flags(base64, BIO_FLAGS_BASE64_NO_NL); + BIO* mem = BIO_new(BIO_s_mem()); + BIO_push(base64, mem); + i2d_PUBKEY_bio(base64, key); + EVP_PKEY_free(key); + BIO_flush(base64); + BUF_MEM* bptr=NULL; + BIO_get_mem_ptr(base64, &bptr); + if (bptr && bptr->length > 0) + ret.append(bptr->data, bptr->length); + BIO_free_all(base64); + return ret; +} diff --git a/xmltoolingtest/SecurityHelperTest.h b/xmltoolingtest/SecurityHelperTest.h index 61e571e..7056012 100644 --- a/xmltoolingtest/SecurityHelperTest.h +++ b/xmltoolingtest/SecurityHelperTest.h @@ -76,12 +76,16 @@ public: TSM_ASSERT_EQUALS("Wrong certificate count", certs.size(), 3); auto_ptr key1(certs[0]->clonePublicKey()); - auto_ptr key2(certs[0]->clonePublicKey()); - auto_ptr key3(certs[0]->clonePublicKey()); + auto_ptr key2(certs[1]->clonePublicKey()); + auto_ptr key3(certs[2]->clonePublicKey()); TSM_ASSERT("PEM/DER keys did not match", SecurityHelper::matches(key1.get(), key2.get())); TSM_ASSERT("DER/PKCS12 keys did not match", SecurityHelper::matches(key2.get(), key3.get())); + TSM_ASSERT_EQUALS("Certificate and its key produced different DER encodings", + SecurityHelper::getDEREncoding(certs[2]), SecurityHelper::getDEREncoding(key1.get()) + ); + for_each(certs.begin(), certs.end(), xmltooling::cleanup()); certs.clear(); }