diff --git a/browserid/lib/ca.js b/browserid/lib/ca.js
index 6e50d4b4f7b560711045dbe24d6c976a50c16bb5..533538ae24180909db8a9a2ac853e69d0808ee3f 100644
--- a/browserid/lib/ca.js
+++ b/browserid/lib/ca.js
@@ -95,8 +95,6 @@ function verifyChain(certChain, publicKey) {
   for (var i =0; i < certChain.length; i++) {
     var cert = certChain[i];
     if (!cert.verify(currentPublicKey)) {
-      console.log("bad cert");
-      console.log(cert);
       return false;
     }
 
@@ -104,8 +102,6 @@ function verifyChain(certChain, publicKey) {
     currentPublicKey = cert.pk;
   }
 
-  console.log("chain works");
-  
   // pk matches?
   return currentPublicKey.serialize() == publicKey.serialize();
 }
diff --git a/browserid/tests/ca-test.js b/browserid/tests/ca-test.js
new file mode 100644
index 0000000000000000000000000000000000000000..2b13df7a3d6616be08d67d25b04701a08a2344f1
--- /dev/null
+++ b/browserid/tests/ca-test.js
@@ -0,0 +1,73 @@
+#!/usr/bin/env node
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla BrowserID.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+require('./lib/test_env.js');
+
+const assert = require('assert'),
+vows = require('vows'),
+start_stop = require('./lib/start-stop.js'),
+wsapi = require('./lib/wsapi.js'),
+email = require('../lib/email.js'),
+ca = require('../lib/ca.js'),
+jwcert = require('../../lib/jwcrypto/jwcert'),
+jws = require('../../lib/jwcrypto/jws');
+
+var suite = vows.describe('ca');
+
+// disable vows (often flakey?) async error behavior
+suite.options.error = false;
+
+// generate a public key
+var kp = jws.getByAlg("RS").KeyPair.generate(64);
+
+var email_addr = "foo@foo.com";
+
+// create a new account via the api with (first address)
+suite.addBatch({
+  "certify a public key": {
+    topic: ca.certify(email_addr, kp.publicKey.serialize()),
+    "verifies": function(r, err) {
+      var cert = new jwcert.JWCert();
+      cert.parse(r);
+      assert.isTrue(ca.verifyChain([cert], kp.publicKey));
+    }
+  }
+});
+
+// run or export the suite.
+if (process.argv[1] === __filename) suite.run();
+else suite.export(module);
diff --git a/browserid/tests/cert-emails-test.js b/browserid/tests/cert-emails-test.js
index 2791468360d628505668afb3a82ac7978ca52ee6..736e310f357d4414750142308b09f874422c4a49 100755
--- a/browserid/tests/cert-emails-test.js
+++ b/browserid/tests/cert-emails-test.js
@@ -43,7 +43,8 @@ start_stop = require('./lib/start-stop.js'),
 wsapi = require('./lib/wsapi.js'),
 email = require('../lib/email.js'),
 ca = require('../lib/ca.js'),
-jwcert = require('../../lib/jwcrypto/jwcert');
+jwcert = require('../../lib/jwcrypto/jwcert'),
+jws = require('../../lib/jwcrypto/jws');
 
 var suite = vows.describe('cert-emails');
 
@@ -101,6 +102,9 @@ suite.addBatch({
 
 var cert_key_url = "/wsapi/cert_key";
 
+var pubkey = '-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMKlDDHBs5/B0uHDF3AZqOqzavAvpESI\nxEy2/6/p0gOhlUhkj/fWnQWyhM4lU3Ts5+aCzCoQvlWDGePphk8H9FMCAwEAAQ==\n-----END PUBLIC KEY-----\n';
+var pk_obj = jws.getByAlg("RS").PublicKey.deserialize(pubkey);
+
 suite.addBatch({
   "cert key with no parameters": {
     topic: wsapi.post(cert_key_url, {}),
@@ -115,16 +119,16 @@ suite.addBatch({
     }
   },
   "cert key invoked with proper argument": {  
-    topic: wsapi.post(cert_key_url, { email: 'syncer@somehost.com', pubkey: '-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMKlDDHBs5/B0uHDF3AZqOqzavAvpESI\nxEy2/6/p0gOhlUhkj/fWnQWyhM4lU3Ts5+aCzCoQvlWDGePphk8H9FMCAwEAAQ==\n-----END PUBLIC KEY-----\n' }),
+    topic: wsapi.post(cert_key_url, { email: 'syncer@somehost.com', pubkey: pubkey }),
     "returns a response with a proper content-type" : function(r, err) {
       assert.strictEqual(r.code, 200);
       assert.isTrue(r.headers['content-type'].indexOf('application/json; charset=utf-8') > -1);
     },
     "returns a proper cert": function(r, err) {
       var cert = new jwcert.JWCert();
-      cert.parse(r.body);
+      cert.parse(JSON.parse(r.body));
 
-      assert.isTrue(ca.verifyChain([cert], '-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMKlDDHBs5/B0uHDF3AZqOqzavAvpESI\nxEy2/6/p0gOhlUhkj/fWnQWyhM4lU3Ts5+aCzCoQvlWDGePphk8H9FMCAwEAAQ==\n-----END PUBLIC KEY-----\n'));
+      assert.isTrue(ca.verifyChain([cert], pk_obj));
     }
   }
   // NOTE: db-test has more thorough tests of the algorithm behind the sync_emails API