Add helpers to encode keys into DER.
authorScott Cantor <cantor.2@osu.edu>
Wed, 15 Apr 2009 22:00:08 +0000 (22:00 +0000)
committerScott Cantor <cantor.2@osu.edu>
Wed, 15 Apr 2009 22:00:08 +0000 (22:00 +0000)
xmltooling/security/SecurityHelper.h
xmltooling/security/impl/SecurityHelper.cpp
xmltoolingtest/SecurityHelperTest.h

index f2a8839..b62bdf5 100644 (file)
@@ -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);
     };
 };
 
index 5de29c7..0ee81ab 100644 (file)
@@ -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<const OpenSSLCryptoKeyRSA*>(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*>(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<const OpenSSLCryptoKeyDSA*>(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*>(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<const OpenSSLCryptoX509*>(cert)->getOpenSSLX509();
+    EVP_PKEY* key = X509_get_pubkey(const_cast<X509*>(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;
+}
index 61e571e..7056012 100644 (file)
@@ -76,12 +76,16 @@ public:
         TSM_ASSERT_EQUALS("Wrong certificate count", certs.size(), 3);
 
         auto_ptr<XSECCryptoKey> key1(certs[0]->clonePublicKey());
-        auto_ptr<XSECCryptoKey> key2(certs[0]->clonePublicKey());
-        auto_ptr<XSECCryptoKey> key3(certs[0]->clonePublicKey());
+        auto_ptr<XSECCryptoKey> key2(certs[1]->clonePublicKey());
+        auto_ptr<XSECCryptoKey> 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<XSECCryptoX509>());
         certs.clear();
     }