[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Handle-info] hsj 8 challenge response "Authentication via Authorization: Handle" via HS_PUBKEY python example.
First of all, use the hdl-convert-key utility to produce a standard PEM file for the handle private key file. (That way you can take advantage of key-decoding functionality from a standard library.)
I've attached a Python example written by my colleague Ben Hadden. It uses "requests" and "PyCrypto". It resolves a handle record, changes the data in the handle value at index 1, and updates the handle record. Change the values in the main() function at the top to reflect your actual situation.
The updateHandleRecord() function does the work. It sends an unauthenticated PUT request, parses the WWW-Authenticate: header from the response to that, constructs an Authorization: header, and sends the request again authenticated.
Let us know if you have any questions!
Robert
import os
import json
import base64
import requests
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
def main():
pathToPrivateKeyPemFile = "/path/to/privatekey.pem"
authId = "300:id/handle"
handle = "handle/to-edit"
ip = "handle.server.ip.address"
port = 8000
handleRecord = getHandleRecord(handle, ip, port)
print handleRecord
emailValue = handleRecord["values"][1]
emailValue["data"]["value"] = "new.email@example.org"
print handleRecord
updateHandleRecord(handle, handleRecord, ip, port, pathToPrivateKeyPemFile, authId);
def getHandleRecord(handle, ip, port):
url = "https://" + ip + ":" + str(port) + "/api/handles/" + handle
r = requests.get(url, verify=False)
handleRecord = r.json()
return handleRecord
def updateHandleRecord(handle, handleRecord, ip, port, pathToPrivateKeyPemFile, authId):
headers = {
"Content-Type": "application/json"
}
url = "https://" + ip + ":" + str(port) + "/api/handles/" + handle
BODY = json.dumps(handleRecord)
#send the request expecting a response with a WWW-Authenticate header
r = requests.put(url, headers=headers, verify=False, data=BODY)
authenticateHeader = r.headers["WWW-Authenticate"]
authenticateHeaderDict = parseAuthenticateHeader(authenticateHeader)
serverNonceBytes = base64.b64decode(authenticateHeaderDict["nonce"])
sessionId = authenticateHeaderDict["sessionId"]
clientNonceBytes = generateClientNonceBytes()
clientNonceString = base64.b64encode(clientNonceBytes)
combinedNonceBytes = serverNonceBytes + clientNonceBytes
signatureBytes = signBytesSHA256(combinedNonceBytes, pathToPrivateKeyPemFile)
signatureString = base64.b64encode(signatureBytes)
authorizationHeaderString = buildAuthorizationString(signatureString, "HS_PUBKEY", "SHA256", sessionId, clientNonceString, authId)
headers["Authorization"] = authorizationHeaderString
#send the request again with a valid correctly signed Authorization header
r2 = requests.put(url, headers=headers, verify=False, data=BODY)
print r2.status_code, r2.reason
return r2
def signBytesSHA256(bytesArray, pathToPrivateKeyPemFile):
key = open(pathToPrivateKeyPemFile, "r").read()
rsakey = RSA.importKey(key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(bytesArray)
sign = signer.sign(digest)
return sign;
def buildAuthorizationString(signatureString, typeString, alg, sessionId, clientNonceString, authId):
result = ('Handle '
'sessionId="' + sessionId + '", '
'cnonce="' + clientNonceString + '", '
'id="' + authId + '", '
'type="' + typeString + '", '
'alg="'+ alg +'", '
'signature="' + signatureString + '"')
return result
def parseAuthenticateHeader(authenticateHeader):
result = {}
tokens = authenticateHeader.split(", ");
for token in tokens:
firstEquals = token.find("=")
key = token[0:firstEquals]
# quick and dirty parsing of the expected WWW-Authenticate headers
if key == "Basic realm":
continue
if key == "Handle sessionId":
key = "sessionId"
value = token[firstEquals+2:len(token)-1]
result[key] = value
return result
def generateClientNonceBytes():
return bytearray(os.urandom(16))
if __name__ == '__main__':
main()
> On Feb 2, 2016, at 9:30 AM, Robert Verkerk <robert.verkerk@surfsara.nl> wrote:
>
> Hi,
>
> We want to use the handle rest-full api. But don’t want to use the basic authentication with HS_SECKEY.
>
> Does anybody have an python example of challenge response "Authentication via Authorization: Handle" using HS_PUBKEY?
> We would like to generate a private/public keypair with hdl-keygen. The public key is stored in the handle database. The private key is known on the client.
>
> We saw the handle technical manual chapter 14.6.4 and further. This shows the basics. But it is not enough to create a working piece of python code.
>
> --
> Greetings,
>
> Robert Verkerk
>
>
>
>
>
>
> _______________________________________________
> Handle-Info mailing list
> Handle-Info@cnri.reston.va.us
> http://www.handle.net/mailman/listinfo/handle-info
_______________________________________________
Handle-Info mailing list
Handle-Info@cnri.reston.va.us
http://www.handle.net/mailman/listinfo/handle-info