TOTP-Support under Gemstone/S

We had yesterday a small video session using whereby and some Smalltalkers diskussed the topic “totp” as second authentification method after an successful login (we were VASmalltalk, VisualWorks and Gemstone related).

To get all work done under Gemstone you need the MSKLibQREncode, the Multibase-Code and one class from the MSK-ModelBaseRuntime package: MSKTOTPSupport.

The MSKTOTPSupport class has three class methods with all stuff needed. Perhaps some methods are defined elsewhere, but you should at least get the ideaa …

totpCurrentValueForSecret: keyArray forTime: aDateAndTime digits: numberOfDigits period: seconds algorithm: aString
” Returns a new value or nil in error case

totpCurrentValueForSecret: keyArray 
forTime: aDateAndTime 
digits: numberOfDigits 
period: seconds 
algorithm: aString
	"^Integer | nil Returns a new value or nil in error case

			MSKTOTPSupport 
               totpCurrentValueForSecret:  'joachim' asByteArray 
               forTime: DateAndTime now 
               digits: 6  
               period: 30 
               algorithm: 'sha256'
	"
	| hmac key  offset binaryValue currentTimeIntervalStep byteArray |

	currentTimeIntervalStep := ((aDateAndTime asSeconds floor - 
                                                  (DateAndTimeANSI  posixSeconds: 0 offset: (Duration zero) ) asSeconds floor) / seconds) floor .

	byteArray := currentTimeIntervalStep asByteArrayOfSize: 8 .

	aString = 'md5' ifTrue:[ hmac := byteArray asMd5HmacWithKey: keyArray ].
	aString = 'sha1' ifTrue:[ hmac := byteArray asSha1HmacWithKey: keyArray  ].
	aString = 'sha256' ifTrue:[ hmac := byteArray asSha256HmacWithKey: keyArray  ].
	aString = 'sha512' ifTrue:[ hmac := byteArray asSha512HmacWithKey: keyArray  ].

	hmac isNil ifTrue:[ ^nil ].

	hmac := hmac asByteArray.

	"letztes byte nehmen"
	offset := ((hmac at: hmac size) asInteger bitAnd:16r0f) +1.

	binaryValue := (((hmac at: offset) bitAnd: 16r7f) bitShift: 24)
							+ (((hmac at: offset + 1) bitAnd: 16rff) bitShift: 16)
							+ (((hmac at: offset + 2) bitAnd: 16rff) bitShift: 8)
							+ (((hmac at: offset + 3) bitAnd: 16rff) ). 

	^binaryValue \\ (10 raisedTo: numberOfDigits)

totpQRStringForSecret: keyByteArray 
label: identification 
period: seconds 
issuer: issuerString 
digits: digits 
algorithm: algName 
icon: iconURL 
color: colorValueStringRRGGBB
"
MSKTOTPSupport 
  totpQRStringForSecret: 'joachim' asByteArray 
  label: 'cati' 
  period: 30 
  issuer: 'GESSCati' 
  digits: nil 
  algorithm: 'sha256' 
  icon: nil

        https://github.com/npmccallum/freeotp-android/blob/master/URI.md
"

| writeStream |

writeStream := WriteStream on: String new.
writeStream
    nextPutAll: 'otpauth://totp/' ;
    "URI-encoded "
    nextPutAll: identification encodeForHTTP ;
    nextPutAll: '?secret=' ;
    nextPutAll: (MultibaseBase32upper new encode: keyByteArray).

(digits notNil and:[ digits ~= 6 ])
    ifTrue:[ writeStream nextPutAll: '&digits=' ; nextPutAll: digits asString  ].


(seconds notNil and:[ seconds ~= 30 ])
    ifTrue:[ writeStream nextPutAll: '&period=' ; nextPutAll: seconds asString  ].

(issuerString pumIsStringAndNotEmpty)
    ifTrue:[ writeStream nextPutAll: '&issuer=' ; nextPutAll: issuerString encodeForHTTP ].

(algName pumIsStringAndNotEmpty and:[ algName ~= 'sha1' ])
    ifTrue:[ writeStream nextPutAll: '&algorithm=' ; nextPutAll: algName ].

(colorValueStringRRGGBB pumIsStringAndNotEmpty)
    ifTrue:[ writeStream nextPutAll: '&color=' ; nextPutAll: colorValueStringRRGGBB ].

(iconURL pumIsStringAndNotEmpty)
    ifTrue:[ writeStream nextPutAll: '&image=' ; nextPutAll: iconURL ].

^writeStream contents

totpSecretAsBased32: keyByteArray
"
MSKTOTPSupport totpSecureKeyBased32: 'joachim' asByteArray
"
^MultibaseBase32upper new encode: keyByteArray

So by writing the following code, we could generate a png showing a QR code, which FreeOTP could use:

(MSKLibQRToolOptions
   newPNGFor: (MSKTOTPSupport
                  totpQRStringForSecret: 'joachim' asByteArray
                  label: 'GessCATI:M.Feldtmann'
                  period: 30
                  issuer: 'Anonymous'
                  digits: 6
                  algorithm: 'sha1'
                  icon: 'https://feldtmann.ddns.net/test.png'
                  color: '808080')
   path: '/var/www/html/Sebastian.png')
      moduleSize: 15 ;
      foreground: Color black ;
      background: Color white ;
      qrToolCreateQRCode

The system uses the local qrencode tool available under Linux and we got the following QR png file – and you may try your FreeOTP with that result.

Some question still remain when other algorithm have to be used, but this will be solved – and how the remaining other algorithm could be inserted.

Working Model – Server Side

Here is a description of a working model (on the server side) and a description of a potential API to manage TOTP systemwide. Sorry, its in German.

Advertisement
This entry was posted in Smalltalk and tagged , , , . Bookmark the permalink.

1 Response to TOTP-Support under Gemstone/S

  1. Pingback: TOTP in Smalltalk – a little experiment – Joachims Small World

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.