2

I'm developing a Django project that will use BankID for authorization and digitally sign. I am using pybankid, and I have nothing but nice things to say about that project. My problem lies with trying to use the code provided by bankIDs documentation.

QRCode Docs

import hashlib
import hmac
import time
 
qr_start_token = rp_response["qrStartToken"]
# "67df3917-fa0d-44e5-b327-edcc928297f8"
 
qr_start_secret = rp_response["qrStartSecret"]
# "d28db9a7-4cde-429e-a983-359be676944c"
 
order_time = time.time()
# (The time in seconds when the response from the BankID service was delivered)
 
qr_time = str(int(time.time() - order_time))
# ("0" or another string with a higher number depending on order_time and current time)
 
qr_auth_code = hmac.new(qr_start_secret, qr_time, hashlib.sha256).hexdigest()
# "dc69358e712458a66a7525beef148ae8526b1c71610eff2c16cdffb4cdac9bf8" (qr_time="0")
# "949d559bf23403952a94d103e67743126381eda00f0b3cbddbf7c96b1adcbce2" (qr_time="1")
# "a9e5ec59cb4eee4ef4117150abc58fad7a85439a6a96ccbecc3668b41795b3f3" (qr_time="2")
# (64 chars hex)
 
qr_data = str.join(".", "bankid", qr_start_token, qr_time, qr_auth_code)
# "bankid.67df3917-fa0d-44e5-b327-edcc928297f8.0.dc69358e712458a66a7525beef148ae8526b1c71610eff2c16cdffb4cdac9bf8" (qr_time="0")
# "bankid.67df3917-fa0d-44e5-b327-edcc928297f8.1.949d559bf23403952a94d103e67743126381eda00f0b3cbddbf7c96b1adcbce2" (qr_time="1")
# "bankid.67df3917-fa0d-44e5-b327-edcc928297f8.2.a9e5ec59cb4eee4ef4117150abc58fad7a85439a6a96ccbecc3668b41795b3f3" (qr_time="2")

I get TypeError: key: expected bytes or bytearray, but got 'str', when I try to convert qr_start_secret to bytes I get Unicode-objects must be encoded before hashing. I'm at a loss. Does anyone have any ideas?

EDIT: Here is my current code, and it works. Currently struggling with how to render a constantly changing QR code value client side, as context will only transfer static values.

if request.META['HTTP_USER_AGENT']:
 ua_string = request.META['HTTP_USER_AGENT']
 user_agent = parse(ua_string)
 if user_agent.is_pc:
                        
  status=client.collect(order_ref=auth["orderRef"])["status"]
                        order_time = time.time()
                        while status == "pending":

  qr_start_token = auth["qrStartToken"]

  qr_start_secret = auth["qrStartSecret"]

  qr_time = str(int(time.time() - order_time))

  qr_auth_code = hmac.new(qr_start_secret.encode(), qr_time.encode(), hashlib.sha256).hexdigest()

  qr_data = ".".join(["bankid", qr_start_token, qr_time, qr_auth_code])

  print(f'qr_data: {qr_data}')

                            
  status=client.collect(order_ref=auth["orderRef"])["status"]

  print(status)

  qr = segno.make(qr_data)
  qr.save('media/img/temp/' + personal_number + '.svg')

  if status == "complete":
   print("Logged on")
   dj_login(request, user)
   return render(request, 'home/auth-login-Success.html')

  time.sleep(1)
Hammertime
  • 23
  • 5

1 Answers1

2

There are multiple issues with their sample code

  1. It looks like qr_start_token and qr_start_secret are strings.
  2. str.join will raise error for receiving 4 arguments

Try:

import hashlib
import hmac
import time
 
qr_start_token = "67df3917-fa0d-44e5-b327-edcc928297f8"
 
qr_start_secret = "d28db9a7-4cde-429e-a983-359be676944c"
 
order_time = time.time()
# (The time in seconds when the response from the BankID service was delivered)
 
qr_time = str(int(time.time() - order_time))
# ("0" or another string with a higher number depending on order_time and current time)
print(f'qr_time: {qr_time}')
qr_auth_code = hmac.new(qr_start_secret.encode(), qr_time.encode(), hashlib.sha256).hexdigest()
# "dc69358e712458a66a7525beef148ae8526b1c71610eff2c16cdffb4cdac9bf8" (qr_time="0")
# "949d559bf23403952a94d103e67743126381eda00f0b3cbddbf7c96b1adcbce2" (qr_time="1")
# "a9e5ec59cb4eee4ef4117150abc58fad7a85439a6a96ccbecc3668b41795b3f3" (qr_time="2")
# (64 chars hex)

print(f'qr_auth_code: {qr_auth_code}')
print(qr_auth_code == "dc69358e712458a66a7525beef148ae8526b1c71610eff2c16cdffb4cdac9bf8")
 
qr_data = str.join(".", ["bankid", qr_start_token, qr_time, qr_auth_code])
# or better
# qr_data = ".".join(["bankid", qr_start_token, qr_time, qr_auth_code])

# "bankid.67df3917-fa0d-44e5-b327-edcc928297f8.0.dc69358e712458a66a7525beef148ae8526b1c71610eff2c16cdffb4cdac9bf8" (qr_time="0")
# "bankid.67df3917-fa0d-44e5-b327-edcc928297f8.1.949d559bf23403952a94d103e67743126381eda00f0b3cbddbf7c96b1adcbce2" (qr_time="1")
# "bankid.67df3917-fa0d-44e5-b327-edcc928297f8.2.a9e5ec59cb4eee4ef4117150abc58fad7a85439a6a96ccbecc3668b41795b3f3" (qr_time="2")

print(f'qr_data: {qr_data}')

output:

qr_time: 0
qr_auth_code: dc69358e712458a66a7525beef148ae8526b1c71610eff2c16cdffb4cdac9bf8
True
qr_data: bankid.67df3917-fa0d-44e5-b327-edcc928297f8.0.dc69358e712458a66a7525beef148ae8526b1c71610eff2c16cdffb4cdac9bf8
buran
  • 13,682
  • 10
  • 36
  • 61
  • Heh, I need 15 rep to upvote you. I think that you have the right answer and I wonder why the demo code was so poorly written. It feels like someone converted it from another language and didn't test it. I am going to render it as an animated QR code and see if I can auth from the BankID mobile app. – Hammertime Oct 26 '21 at 06:12
  • I agree it was not tested. And you can [accept an answer that solves your problem](https://stackoverflow.com/help/someone-answers). – buran Oct 26 '21 at 06:31
  • Probably you can contact them and notify for this problem with their sample code. – buran Oct 26 '21 at 06:43
  • It did solve that problem, but opened up a can of worms... Like how do I render an ever changing QR code from Django views onto a page. I don't want to render the secret code in JS and perform the same function there. Sigh, more to learn. – Hammertime Oct 26 '21 at 12:46