{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Notebook 1: X.509 certificates"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Jupyter notebook cheat sheet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Use Shift+Enter to run the current cell\n",
    "print('Hello!')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# You may also use Alt+Enter to run the current cell, then create a new cell right below\n",
    "from datetime import datetime\n",
    "print('This is the time right now: %s' % datetime.now())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# If needed, pause the cell edition with Ctrl-M.\n",
    "# Then you can delete the current cell with D+D. You can also undo cell deletion with Z.\n",
    "# Finally, should Jupyter become stuck in execution, use Kernel/Interrupt from the menu bar.\n",
    "print('Got it!')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data manipulation with Scapy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from scapy.all import *\n",
    "load_layer('tls')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "keystr = open('raw_data/pki/ca_key.der', 'rb').read()\n",
    "print(repr(keystr))\n",
    "# (btw, you can hide the output of a cell by double-clicking on the left of the output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "privkey = RSAPrivateKey(keystr)\n",
    "privkey.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "v = privkey.version\n",
    "print('The \\'version\\' stripped from any ASN.1 encoding is 0x%02x.' % v.val)\n",
    "print('The \\'version\\' field corresponds to bytes  %r.' % raw(v))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "privkey.version = ASN1_INTEGER(1)\n",
    "privkey.modulus.val *= 2\n",
    "privkey.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "print('Original data: %r...' % keystr[:13])\n",
    "print('New version bytes:          %r' % raw(privkey.version))\n",
    "print('New modulus bytes:                      %r...' % raw(privkey.modulus)[:6])\n",
    "print('Rebuilt data:  %r...' % raw(privkey)[:13])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## X.509 certificate features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Let's reload the original key, then let's load a certificate associated with it\n",
    "privkey = RSAPrivateKey(keystr)\n",
    "cert = X509_Cert(open('raw_data/pki/ca_cert.der', 'rb').read())\n",
    "cert.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "cert.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.show()\n",
    "cert.tbsCertificate.subject[-1].rdn[0].show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "cert.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.modulus == privkey.modulus"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "cert.tbsCertificate.extensions[2].show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "cert.signatureAlgorithm.algorithm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scapy crypto tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Let's reload the key with Scapy's crypto-enhanced wrapper\n",
    "privkey = PrivKey('raw_data/pki/ca_key.der')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "privkey.der == keystr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "print(privkey.key)\n",
    "print(privkey.pubkey)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# We can compute the RSA signature over the part of the certificate which is to be signed\n",
    "privkey.sign(raw(cert.tbsCertificate))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "cert.signatureValue"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# We can quickly modify a certificate field and update the signature accordingly\n",
    "cert.tbsCertificate.serialNumber.val = 0xdeadcafe\n",
    "cert.tbsCertificate.subject[-1].rdn[0].value.val = 'my new deadcafe CA'    \n",
    "cert2 = privkey.resignCert(cert)\n",
    "cert2.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
