Closed jcallahan526 closed 3 years ago
How could we adapt this to return the TOPT codes from the Secret Key?
You can use the generateCodes
method from the TOTP class to get the codes from a given secret:
List<String> result = TOTP.generateCodes('12345678901234567890', 0000000000000001L, 8, 'hmacSHA1');
The second item contains the code as the RFC 6238. If you want to generate multiple codes for different 30s intervals, you can put this within a loop and modify the second attribute (the time).
@renatoliveira - Thanks for the super quick response! I inputted my Secret Key (CSDPEB2NZFTUEL54EOMWXBGX7HC4TPNL) into the script and this generated the TOTP codes However these codes do not match what I am seeing in my Authenticator app (see attached)
@renatoliveira - Thanks for the super quick response! I inputted my Secret Key (CSDPEB2NZFTUEL54EOMWXBGX7HC4TPNL) into the script and thisgenerated the TOTP codes However these codes do not match what I am seeing in my Authenticator app (see attached)
One of the things I immediately see wrong with your picture is that you tried to use the first millisecond of the Linux Era (the long in the second parameter) instead of the current time, this might be one.
Now, I don't know why, but I tried with other codes and couldn't get the algorithm to work with other codes either. It is very weird because it works with the first example on the RFC (considering a key "12345678901234567890" and the value of time as "0000000000000001" and that the number of digits is 8, the output is "94287082" - which is correct).
Good thing to have found this, I might need to take another look into the code that converts the secret from the friendly format to the actual thing used internally.
@renatoliveira - again thanks for the quick response! I attempted to reverse engineer this.... I used Test123 as my Key in the following scripts...
System.debug(new TOTP.KeyURI('Test123', 'renato@totp.demo', 'TOTP, Inc').getURL());
System.debug(TOTP.generateCodes('Test123', System.now().getTime(), 6, 'hmacSha1'));
The output is as follows
[#4 21:42:36.46] otpauth://totp/TOTP, Inc:renato@totp.demo?secret=KRSXG5BRGIZQ====&issuer=TOTP, Inc&algorithm=SHA1&period=30&digits=6
[#5 21:42:36.46] Generating for step 33851f5
[#6 21:42:36.46] Generating for step 33851f6
[#7 21:42:36.46] (779526, 456955)
The secret is the Base32 Encoded value of the Key.
When I manually enter this into Authenticator the codes align (see attached).
However I cannot decode the Secret Key from my Salesforce QR Code - CSDPEB2NZFTUEL54EOMWXBGX7HC4TPNL
otpauth://totp/Demo:jeff526%40gmail.com?secret=CSDPEB2NZFTUEL54EOMWXBGX7HC4TPNL&issuer=Demo
@renatoliveira - again thanks for the quick response! I attempted to reverse engineer this.... I used Test123 as my Key in the following scripts...
System.debug(new TOTP.KeyURI('Test123', 'renato@totp.demo', 'TOTP, Inc').getURL()); System.debug(TOTP.generateCodes('Test123', System.now().getTime(), 6, 'hmacSha1'));
The output is as follows
[#4 21:42:36.46] otpauth://totp/TOTP, Inc:renato@totp.demo?secret=KRSXG5BRGIZQ====&issuer=TOTP, Inc&algorithm=SHA1&period=30&digits=6 [#5 21:42:36.46] Generating for step 33851f5 [#6 21:42:36.46] Generating for step 33851f6 [#7 21:42:36.46] (779526, 456955)
The secret is the Base32 Encoded value of the Key. When I manually enter this into Authenticator the codes align (see attached). However I cannot decode my actual secret - CSDPEB2NZFTUEL54EOMWXBGX7HC4TPNL
That's good news, actually. This means that the problem is with the decoding of the secret value! This is actually great since you can generate the code with Apex and save it as is (not encoded) to compare later in the authentication process.
So we are looking to store the Secret Values in our Salesforce Org and then use them to generate the TOTP codes.
Is this possible?
So we are looking to store the Secret Values in our Salesforce Org and then use them to generate the TOTP codes. Is this possible?
Yes. Well... you would just use that key URI method and extract the secret parameter and store it somewhere safe. Having the secret you can generate the URI to display a QR Code to your users later (with a LWC, for example).
@renatoliveira - thanks for your quick responses!
Is it possible to generate the TOPT from only the encoded Base32 Secret generated by Salesforce - i.e CSDPEB2NZFTUEL54EOMWXBGX7HC4TPNL ?
Per the article below it does not appear that we can decode the Secret to generate the Key. https://developer.salesforce.com/forums/?id=906F0000000AdjDIAS
We do not have the decoded Key, only the encoded Secret. We would be looking to store these to generate the TOPT's
@renatoliveira - thanks for your quick responses!
Is it possible to generate the TOPT from only the encoded Base32 Secret generated by Salesforce - i.e CSDPEB2NZFTUEL54EOMWXBGX7HC4TPNL ?
Per the article below it does not appear that we can decode the Secret to generate the Key. https://developer.salesforce.com/forums/?id=906F0000000AdjDIAS
We do not have the decoded Key, only the encoded Secret. We would be looking to store these to generate the TOPT's
I don't think that's possible (with the current implementation in this repo). You need the unencoded secret for the method to work. Currently the class only implements one direction (the encoding to a Base32 value).
You can generate the code on Salesforce and then store it on the same transaction though, or even store the secret in an encrypted form:
getURL
method.
How could we adapt this to return the TOPT codes from the Secret Key?