mirror of
https://github.com/certbot/certbot.git
synced 2026-06-03 22:08:07 -04:00
Merge branch 'master' of github.com:research/chocolate
This commit is contained in:
commit
93cec72f7a
10 changed files with 58 additions and 24 deletions
|
|
@ -2,23 +2,6 @@ In this directory are tools that will run on webservers for sysadmins to
|
|||
automatically obtain their certs
|
||||
|
||||
|
||||
Set CHOCOLATESERVER environment variable for "make deploy" and client.py!
|
||||
|
||||
|
||||
chocolate.py - server-side, requires web.py (python-webpy),
|
||||
PyCrypto (python-crypto), redis, python-redis, python-protobuf,
|
||||
python-nss
|
||||
probably wants to run under a web server like lighttpd with fastcgi
|
||||
Set CHOCOLATESERVER environment variable for client.py!
|
||||
|
||||
client.py - experimental tool for making requests and parsing replies
|
||||
|
||||
chocolate_protocol.proto - protocol definition; needs protobuf-compiler
|
||||
|
||||
sni_challenge -
|
||||
Assumes Apache server with name based virtual hosts is running
|
||||
(for intended address).
|
||||
Call perform_sni_cert_challenge(address, r, nonce) to do the whole
|
||||
challenge.
|
||||
Example code is given in main method
|
||||
Right now requires full path specification of CSR/KEY in the Global
|
||||
Variables (how should this be specified?)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ deploy: chocolate_protocol_pb2.py chocolate.py CSR.py pkcs10.py daemon.py
|
|||
|
||||
chocolate_protocol_pb2.py: chocolate_protocol.proto
|
||||
protoc chocolate_protocol.proto --python_out=.
|
||||
cp -p chocolate_protocol_pb2.py ../client-webserver/
|
||||
|
||||
clean:
|
||||
rm -f *.pyc
|
||||
|
|
@ -1,2 +1,22 @@
|
|||
In this directory is a reference CA implementation of the Chocolate protocol,
|
||||
DV and signing mechanism.
|
||||
|
||||
Set CHOCOLATESERVER environment variable for "make deploy"!
|
||||
|
||||
|
||||
chocolate.py - server-side, requires web.py (python-webpy),
|
||||
PyCrypto (python-crypto) 2.3 (not 2.1!!), redis, python-redis,
|
||||
python-protobuf, python-nss
|
||||
probably wants to run under a web server like lighttpd with fastcgi
|
||||
|
||||
|
||||
chocolate_protocol.proto - protocol definition; needs protobuf-compiler
|
||||
|
||||
sni_challenge -
|
||||
Assumes Apache server with name based virtual hosts is running
|
||||
(for intended address).
|
||||
Call perform_sni_cert_challenge(address, r, nonce) to do the whole
|
||||
challenge.
|
||||
Example code is given in main method
|
||||
Right now requires full path specification of CSR/KEY in the Global
|
||||
Variables (how should this be specified?)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
import web, redis, time
|
||||
import CSR
|
||||
from Crypto.Hash import SHA256, HMAC
|
||||
from Crypto import Random
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto import Random
|
||||
from chocolate_protocol_pb2 import chocolatemessage
|
||||
from google.protobuf.message import DecodeError
|
||||
|
||||
|
|
@ -102,6 +103,10 @@ class session(object):
|
|||
"""Has there already been a signing request made in this session?"""
|
||||
return sessions.hget(self.id, "state") is not None
|
||||
|
||||
def pubkey(self):
|
||||
"""Return the PEM-formatted subject public key from the CSR."""
|
||||
return CSR.pubkey(sessions.hget(self.id, "csr"))
|
||||
|
||||
def cert(self):
|
||||
"""Return the issued certificate."""
|
||||
return sessions.hget(self.id, "cert")
|
||||
|
|
@ -276,8 +281,12 @@ class session(object):
|
|||
chall.type = int(c["type"])
|
||||
chall.name = c["name"]
|
||||
chall.succeeded = (c["satisfied"] == "True") # TODO: this contradicts comment in protocol about meaning of "succeeded"
|
||||
chall.data.append(c["dvsni:r"])
|
||||
# Calculate y
|
||||
dvsni_r = c["dvsni:r"]
|
||||
y = RSA.importKey(self.pubkey()).encrypt(dvsni_r, None)[0]
|
||||
# In dvsni, we send nonce, y, ext
|
||||
chall.data.append(c["dvsni:nonce"])
|
||||
chall.data.append(y)
|
||||
chall.data.append(c["dvsni:ext"])
|
||||
|
||||
def POST(self):
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
# If the client never checks in, the daemon can keep advancing
|
||||
# the request's state, which may not be the right behavior.
|
||||
|
||||
import redis, time
|
||||
import redis, time, CSR
|
||||
r = redis.Redis()
|
||||
|
||||
from Crypto.Hash import SHA256, HMAC
|
||||
|
|
@ -132,8 +132,10 @@ def issue(session):
|
|||
return
|
||||
# Note that we can push this back into the original queue.
|
||||
# TODO: need to add a way to make sure we don't test the same
|
||||
# TODO: actually issue the cert
|
||||
r.hset(session, "cert", "----ISSUED CERT GOES HERE----")
|
||||
# TODO: actually make this call issue the cert
|
||||
csr = r.hget(session, "csr")
|
||||
cert = CSR.issue(csr)
|
||||
r.hset(session, "cert", cert)
|
||||
if False: # once issuing cert succeeded
|
||||
r.hset(session, "state", "done")
|
||||
r.lpush("pending-done", session)
|
||||
|
|
@ -3,6 +3,7 @@ from Crypto import Random
|
|||
import sni_support
|
||||
import hmac
|
||||
import hashlib
|
||||
import binascii
|
||||
|
||||
S_SIZE = 32
|
||||
NONCE_SIZE = 32
|
||||
|
|
@ -15,6 +16,13 @@ def byteToHex(byteStr):
|
|||
return ''.join(["%02X" % ord(x) for x in byteStr]).strip()
|
||||
|
||||
def check_challenge_value(ext_value, r):
|
||||
"""
|
||||
Checks that a challenge response actually passes the challenge
|
||||
|
||||
ext_value: string returned by client-webserver's X.509 cert
|
||||
chocolate extension
|
||||
r: secret random key (binary string) chosen by server-CA
|
||||
"""
|
||||
s = ext_value[0:S_SIZE]
|
||||
mac = ext_value[S_SIZE:]
|
||||
expected_mac = hmac.new(r, str(s), hashlib.sha256).digest()
|
||||
|
|
@ -30,6 +38,17 @@ def check_challenge_value(ext_value, r):
|
|||
return False
|
||||
|
||||
def verify_challenge(address, r, nonce):
|
||||
"""
|
||||
Verifies an SNI challenge at address (assumes port 443)
|
||||
|
||||
address: string host (e.g. "127.0.0.1")
|
||||
r: secret random key (binary string)
|
||||
nonce: ascii string of nonce (e.g. "66f58cfb...")
|
||||
|
||||
returns (result, reason)
|
||||
result: True/False for passed/failed verification
|
||||
reason: Human-readable string describing reason for result
|
||||
"""
|
||||
sni_name = nonce + ".chocolate"
|
||||
|
||||
context = M2Crypto.SSL.Context()
|
||||
|
|
@ -72,7 +91,7 @@ def main():
|
|||
r = Random.get_random_bytes(NONCE_SIZE)
|
||||
r = "testValueForR"
|
||||
encryptedValue = testkey.encrypt(r, 0)
|
||||
valid, response = verify_challenge("127.0.0.1", r, nonce)
|
||||
valid, response = verify_challenge("127.0.0.1", r, binascii.hexlify(nonce))
|
||||
print response
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Reference in a new issue