<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm) in Application Development and Automation Discussions</title>
    <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737074#M2020833</link>
    <description>&lt;P&gt;Thanks Lars,&lt;/P&gt;&lt;P&gt;I am able to generate HASH(Alpha numeric) and wanted to get 6 digit Code like java is producing. Not sure how offset and trunc variable is working. &lt;/P&gt;&lt;P&gt;Any pointer would be helpful.&lt;/P&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;Nikhil&lt;/P&gt;</description>
    <pubDate>Thu, 27 Jul 2023 22:57:40 GMT</pubDate>
    <dc:creator>former_member202253</dc:creator>
    <dc:date>2023-07-27T22:57:40Z</dc:date>
    <item>
      <title>SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737069#M2020828</link>
      <description>&lt;P&gt;Dear Guru's,&lt;/P&gt;
  &lt;P&gt;I hope you are well.&lt;U&gt;&lt;/U&gt;&lt;U&gt;&lt;/U&gt;&lt;/P&gt;
  &lt;P&gt;We have requirement to generate TOTP using ABAP and I got stuck on the requirement to generate TOTP tokens from SAP ABAP. This is very easy and doable in JAVA but challenging in ABAP.&lt;U&gt;&lt;/U&gt;&lt;U&gt;&lt;/U&gt;&lt;/P&gt;
  &lt;P&gt;Based on my analysis this can be doable using Class: CL_ABAP_HMAC.&lt;U&gt;&lt;/U&gt;&lt;U&gt;&lt;/U&gt;&lt;/P&gt;
  &lt;P&gt;I am trying to convert Java Code to ABAP but I am stuck on some of the places where byte Array in Java Code and not able to make it result like java code.&lt;/P&gt;
  &lt;P&gt;&lt;IMG class="migrated-image" src="https://community.sap.com/legacyfs/online/storage/attachments/storage/7/attachments/2185061-image.png" /&gt;&lt;/P&gt;
  &lt;P&gt;Also I have gone through : &lt;A href="https://datatracker.ietf.org/doc/html/rfc6238" target="_blank"&gt;https://datatracker.ietf.org/doc/html/rfc6238&lt;/A&gt; and based on this I was trying code for JAVA and ABAP. &lt;U&gt;&lt;/U&gt;&lt;U&gt;&lt;/U&gt;&lt;/P&gt;
  &lt;P&gt;I am attaching both codes for your reference. &lt;U&gt;&lt;/U&gt;&lt;U&gt;&lt;/U&gt;&lt;/P&gt;
  &lt;P&gt;It would be helpful if you can advise. How can I get results like in the Java class?&lt;U&gt;&lt;/U&gt;&lt;U&gt;&lt;/U&gt;&lt;/P&gt;
  &lt;P&gt;Thank you&lt;U&gt;&lt;/U&gt;&lt;U&gt;&lt;/U&gt;&lt;/P&gt;
  &lt;P&gt;ABAP Code: &lt;/P&gt; 
  &lt;PRE&gt;&lt;CODE&gt;&amp;lt;br&amp;gt;DATA: im_date TYPE sy-datum.&amp;lt;br&amp;gt;DATA: im_time       TYPE sy-uzeit,&amp;lt;br&amp;gt;      im_msec       TYPE numc7,&amp;lt;br&amp;gt;      l_xstring_key TYPE xstring,&amp;lt;br&amp;gt;      l_key         TYPE string,&amp;lt;br&amp;gt;      ex_timestamp  TYPE string.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;DATA: l_date TYPE sy-datum.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;DATA: l_days_timestamp TYPE timestampl.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;DATA: l_secs_timestamp TYPE timestampl.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;DATA: l_i_days TYPE i.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;DATA: l_i_sec TYPE i.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;DATA: l_timestamp TYPE timestampl.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;DATA: l_dummy TYPE string.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;DATA: ts2(25) TYPE c,&amp;lt;br&amp;gt;      ts      TYPE timestampl.&amp;lt;br&amp;gt;GET TIME STAMP FIELD ts.&amp;lt;br&amp;gt;DATA: dat TYPE date,&amp;lt;br&amp;gt;      tim TYPE time,&amp;lt;br&amp;gt;      tz  TYPE timezone.&amp;lt;br&amp;gt;MOVE ts TO ts2.&amp;lt;br&amp;gt;CONDENSE ts2.&amp;lt;br&amp;gt;DATA: t1(10),t2(13) TYPE c.&amp;lt;br&amp;gt;CONVERT TIME STAMP ts TIME ZONE sy-zonlo INTO DATE dat TIME tim.&amp;lt;br&amp;gt;CONCATENATE dat+0(4) dat+4(2) dat+6(2) INTO t1.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;im_date =  dat.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;CONCATENATE tim+0(2)  tim+2(2)  tim+4(2)   INTO t2.&amp;lt;br&amp;gt;im_time = tim.&amp;lt;br&amp;gt;im_msec = ts2+15(7).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;*-----------------------------------------------------------------------&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;* milliseconds for the days since January 1, 1970, 00:00:00 GMT&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;* one day has 86400 seconds&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;l_date = '19700101'.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;l_i_days = im_date - l_date.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;* timestamp for days past in seconds&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;l_days_timestamp = l_i_days * 86400.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;l_i_sec = im_time.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;* timestamp for time at present day&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;l_secs_timestamp = l_i_sec.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;l_timestamp = ( l_days_timestamp + l_secs_timestamp ) * 1000.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;ex_timestamp = l_timestamp.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;SPLIT ex_timestamp AT '.' INTO ex_timestamp l_dummy.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;ex_timestamp = ex_timestamp + im_msec.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;SHIFT ex_timestamp RIGHT DELETING TRAILING space.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;SHIFT ex_timestamp LEFT DELETING LEADING space.&amp;lt;br&amp;gt;DATA(l) = ex_timestamp / 1000.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;ex_timestamp = round( val = ( ( round( val = l  dec = 0 ) - 0 ) / 30 ) dec = 0 ).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;TYPES t_long_int(16) TYPE p DECIMALS 0.&amp;lt;br&amp;gt;DATA: number TYPE t_long_int,&amp;lt;br&amp;gt;      result TYPE string.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;number = ex_timestamp.&amp;lt;br&amp;gt;PERFORM convert_base10_to_base16 USING    number&amp;lt;br&amp;gt;                                 CHANGING result.&amp;lt;br&amp;gt;WRITE: / number, '--&amp;gt;', result.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;TRY.&amp;lt;br&amp;gt;    l_key  = '3132333435363738393031323334353637383930'.&amp;lt;br&amp;gt;    l_xstring_key  = cl_abap_hmac=&amp;gt;string_to_xstring( l_key ).&amp;lt;br&amp;gt;  CATCH cx_abap_message_digest.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;ENDTRY.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;clear : result.&amp;lt;br&amp;gt;number = ex_timestamp.&amp;lt;br&amp;gt;PERFORM  gettotp USING    number&amp;lt;br&amp;gt;                          l_xstring_key&amp;lt;br&amp;gt;                          CHANGING result.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;  write /       result.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;FORM gettotp USING    timeindex TYPE t_long_int&amp;lt;br&amp;gt;                      key TYPE xstring&amp;lt;br&amp;gt;                     CHANGING result TYPE string.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;*TRY.&amp;lt;br&amp;gt;CALL METHOD cl_abap_hmac=&amp;gt;get_instance&amp;lt;br&amp;gt;  EXPORTING&amp;lt;br&amp;gt;    if_algorithm = 'SHA1'&amp;lt;br&amp;gt;    if_key       = key&amp;lt;br&amp;gt;  receiving&amp;lt;br&amp;gt;    ro_object    = DATA(lo_hmac)&amp;lt;br&amp;gt;    .&amp;lt;br&amp;gt;* CATCH cx_abap_message_digest .&amp;lt;br&amp;gt;*ENDTRY.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;data(l_string) = CONV string( timeindex ).&amp;lt;br&amp;gt;  TRY.&amp;lt;br&amp;gt;      CALL METHOD lo_hmac-&amp;gt;final&amp;lt;br&amp;gt;        EXPORTING&amp;lt;br&amp;gt;          if_data = cl_abap_hmac=&amp;gt;string_to_xstring( l_string  )&amp;lt;br&amp;gt;      if_offset        = 0&amp;lt;br&amp;gt;      if_length        = strlen( l_string )&amp;lt;br&amp;gt;    IMPORTING&amp;lt;br&amp;gt;      ef_hmacstring    = result&amp;lt;br&amp;gt;*    ef_hmacxstring   =&amp;lt;br&amp;gt;*    ef_hmacb64string =&amp;lt;br&amp;gt;      .&amp;lt;br&amp;gt;    CATCH cx_abap_message_digest .&amp;lt;br&amp;gt;  ENDTRY.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;*TRY.&amp;lt;br&amp;gt;CALL METHOD lo_hmac-&amp;gt;to_base64&amp;lt;br&amp;gt;  RECEIVING&amp;lt;br&amp;gt;    er_hmacb64string = data(l_base)&amp;lt;br&amp;gt;    .&amp;lt;br&amp;gt;* CATCH cx_abap_message_digest .&amp;lt;br&amp;gt;*ENDTRY.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;    endform.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;FORM convert_base10_to_base16 USING    number TYPE t_long_int&amp;lt;br&amp;gt;                              CHANGING result TYPE string.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;  DATA:&amp;lt;br&amp;gt;    rest  TYPE t_long_int,&amp;lt;br&amp;gt;    digit TYPE c.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;  rest = number MOD 16.&amp;lt;br&amp;gt;  CASE rest.&amp;lt;br&amp;gt;    WHEN 0 OR 1 OR 2 OR 3 OR 4 OR 5 OR 6 OR 7 OR 8 OR 9.&amp;lt;br&amp;gt;      WRITE rest TO digit LEFT-JUSTIFIED NO-SIGN.&amp;lt;br&amp;gt;    WHEN 10.&amp;lt;br&amp;gt;      digit = 'A'.&amp;lt;br&amp;gt;    WHEN 11.&amp;lt;br&amp;gt;      digit = 'B'.&amp;lt;br&amp;gt;    WHEN 12.&amp;lt;br&amp;gt;      digit = 'C'.&amp;lt;br&amp;gt;    WHEN 13.&amp;lt;br&amp;gt;      digit = 'D'.&amp;lt;br&amp;gt;    WHEN 14.&amp;lt;br&amp;gt;      digit = 'E'.&amp;lt;br&amp;gt;    WHEN 15.&amp;lt;br&amp;gt;      digit = 'F'.&amp;lt;br&amp;gt;  ENDCASE.&amp;lt;br&amp;gt;  CONCATENATE digit result INTO result.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;  rest = number DIV 16.&amp;lt;br&amp;gt;  IF rest &amp;gt; 0.&amp;lt;br&amp;gt;    PERFORM convert_base10_to_base16 USING    rest&amp;lt;br&amp;gt;                                     CHANGING result.&amp;lt;br&amp;gt;  ENDIF.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;ENDFORM.&lt;/CODE&gt;&lt;/PRE&gt;
  &lt;P&gt;Java Code: &lt;/P&gt; 
  &lt;PRE&gt;&lt;CODE&gt;package testJavaCode;&amp;lt;br&amp;gt;import java.lang.reflect.UndeclaredThrowableException;&amp;lt;br&amp;gt;import java.security.GeneralSecurityException;&amp;lt;br&amp;gt;import java.security.NoSuchAlgorithmException;&amp;lt;br&amp;gt;import java.text.DateFormat;&amp;lt;br&amp;gt;import java.text.SimpleDateFormat;&amp;lt;br&amp;gt;import java.util.Date;&amp;lt;br&amp;gt;import javax.crypto.Mac;&amp;lt;br&amp;gt;import javax.crypto.spec.SecretKeySpec;&amp;lt;br&amp;gt;import java.math.BigInteger;&amp;lt;br&amp;gt;import java.nio.ByteBuffer;&amp;lt;br&amp;gt;import java.util.TimeZone;&amp;lt;br&amp;gt;public class TOTP2 {&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;    &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;    /**&amp;lt;br&amp;gt;     * This method converts HEX string to Byte[]&amp;lt;br&amp;gt;     *&amp;lt;br&amp;gt;     * @param hex   the HEX string&amp;lt;br&amp;gt;     *&amp;lt;br&amp;gt;     * @return      A byte array&amp;lt;br&amp;gt;     */&amp;lt;br&amp;gt;    private static byte[] hexStr2Bytes(String hex){&amp;lt;br&amp;gt;        // Adding one byte to get the right conversion&amp;lt;br&amp;gt;        // values starting with "0" can be converted&amp;lt;br&amp;gt;        byte[] bArray = new BigInteger("10" + hex,16).toByteArray();&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;        // Copy all the REAL bytes, not the "first"&amp;lt;br&amp;gt;        byte[] ret = new byte[bArray.length - 1];&amp;lt;br&amp;gt;        for (int i = 0; i &amp;lt; ret.length ; i++)&amp;lt;br&amp;gt;            ret[i] = bArray[i+1];&amp;lt;br&amp;gt;        return ret;&amp;lt;br&amp;gt;    }&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;    private static final int[] DIGITS_POWER&amp;lt;br&amp;gt;    // 0 1  2   3    4     5      6       7        8&amp;lt;br&amp;gt;    = {1,10,100,1000,10000,100000,1000000,10000000,100000000 };&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;    /**&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;    /**&amp;lt;br&amp;gt;     * This method generates an TOTP value for the given&amp;lt;br&amp;gt;     * set of parameters.&amp;lt;br&amp;gt;     *&amp;lt;br&amp;gt;     * @param key   the shared secret, HEX encoded&amp;lt;br&amp;gt;     * @param time     a value that reflects a time&amp;lt;br&amp;gt;     * @param returnDigits     number of digits to return&amp;lt;br&amp;gt;     * @param crypto    the crypto function to use&amp;lt;br&amp;gt;     *&amp;lt;br&amp;gt;     * @return      A numeric String in base 10 that includes&amp;lt;br&amp;gt;     *              {@link truncationDigits} digits&amp;lt;br&amp;gt;     * @throws NoSuchAlgorithmException &amp;lt;br&amp;gt;     */&amp;lt;br&amp;gt;    public static long generateTOTP(byte[] key,&amp;lt;br&amp;gt;            long timeindex&amp;lt;br&amp;gt;            ) throws Exception {&amp;lt;br&amp;gt;        SecretKeySpec signkey = new SecretKeySpec(key , "HmacSHA1");&amp;lt;br&amp;gt;        &amp;lt;br&amp;gt;        ByteBuffer bufferobj = ByteBuffer.allocate(8);&amp;lt;br&amp;gt;        &amp;lt;br&amp;gt;        bufferobj.putLong(timeindex);&amp;lt;br&amp;gt;        &amp;lt;br&amp;gt;        byte[] timeBytesobj = bufferobj.array();&amp;lt;br&amp;gt;        &amp;lt;br&amp;gt;        Mac macobj = Mac.getInstance("HmacSHA1");&amp;lt;br&amp;gt;        &amp;lt;br&amp;gt;        macobj.init(signkey);&amp;lt;br&amp;gt;        &amp;lt;br&amp;gt;        byte[] hash = macobj.doFinal(timeBytesobj);&amp;lt;br&amp;gt;        &amp;lt;br&amp;gt;        int offset = hash[19] &amp;amp; 0xf;&amp;lt;br&amp;gt;        long trunc = hash[offset] &amp;amp; 0x7f;&amp;lt;br&amp;gt;        for ( int i = 1; i &amp;lt; 4 ; i++)&amp;lt;br&amp;gt;        {&amp;lt;br&amp;gt;            trunc &amp;lt;&amp;lt;= 8;&amp;lt;br&amp;gt;            trunc |= hash[offset + i]  &amp;amp; 0xff;&amp;lt;br&amp;gt;            &amp;lt;br&amp;gt;        }&amp;lt;br&amp;gt;        return ( trunc %= 1000000 );&amp;lt;br&amp;gt;    }&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;    &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;    public static void main(String[] args) {&amp;lt;br&amp;gt;        // Seed for HMAC-SHA1 - 20 bytes&amp;lt;br&amp;gt;        String seed = "3132333435363738393031323334353637383930";&amp;lt;br&amp;gt;  &amp;lt;br&amp;gt;        long T0 = 0;&amp;lt;br&amp;gt;        long X = 30;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;        try{&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;            &amp;lt;br&amp;gt;                long T = (56344362 - T0)/X;&amp;lt;br&amp;gt;                &amp;lt;br&amp;gt;                System.out.println(generateTOTP(hexStr2Bytes(seed), T));&amp;lt;br&amp;gt;                &amp;lt;br&amp;gt;                &amp;lt;br&amp;gt;            &amp;lt;br&amp;gt;        }catch (final Exception e){&amp;lt;br&amp;gt;            System.out.println("Error : " + e);&amp;lt;br&amp;gt;        }&amp;lt;br&amp;gt;    }&amp;lt;br&amp;gt;}&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;/CODE&gt;&lt;/PRE&gt;
  &lt;P&gt;&lt;A href="https://answers.sap.com/storage/temp/2185143-java-totp-class1.txt" data-attachment="2185143"&gt;java-totp-class1.txt&lt;/A&gt;&lt;/P&gt;
  &lt;P&gt;Regards,&lt;/P&gt;
  &lt;P&gt;Nikhil&lt;/P&gt;</description>
      <pubDate>Wed, 26 Jul 2023 19:26:52 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737069#M2020828</guid>
      <dc:creator>former_member202253</dc:creator>
      <dc:date>2023-07-26T19:26:52Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737070#M2020829</link>
      <description>&lt;P&gt;Your code is full of &amp;lt;br&amp;gt;, could you paste the code without &amp;lt;br&amp;gt; please?&lt;/P&gt;&lt;P&gt;Ctrl+Shift+V can help you (unformatted paste).&lt;/P&gt;</description>
      <pubDate>Thu, 27 Jul 2023 05:29:07 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737070#M2020829</guid>
      <dc:creator>Sandra_Rossi</dc:creator>
      <dc:date>2023-07-27T05:29:07Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737071#M2020830</link>
      <description>&lt;P&gt;Hi Sandra, Attached code file.&lt;/P&gt;</description>
      <pubDate>Thu, 27 Jul 2023 15:03:12 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737071#M2020830</guid>
      <dc:creator>former_member202253</dc:creator>
      <dc:date>2023-07-27T15:03:12Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737072#M2020831</link>
      <description>&lt;P&gt;For the code example, I guess its for &lt;A href="https://datatracker.ietf.org/doc/html/rfc4226" target="test_blank"&gt;https://datatracker.ietf.org/doc/html/rfc4226&lt;/A&gt; ?&lt;/P&gt;&lt;P&gt;Anyhow,&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&amp;amp; = bit and = BIT-AND in ABAP&lt;/LI&gt;&lt;LI&gt;For shifting left, its easiest to multiply with 2^num_of_bits, note that ABAP internally uses 32bit integer for calculations&lt;/LI&gt;&lt;LI&gt;% = modulus = MOD in ABAP&lt;/LI&gt;&lt;/UL&gt;</description>
      <pubDate>Thu, 27 Jul 2023 16:08:30 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737072#M2020831</guid>
      <dc:creator>larshp</dc:creator>
      <dc:date>2023-07-27T16:08:30Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737073#M2020832</link>
      <description>&lt;P&gt;Just edit your question and remove the &amp;lt;br&amp;gt;s.&lt;/P&gt;</description>
      <pubDate>Thu, 27 Jul 2023 18:40:56 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737073#M2020832</guid>
      <dc:creator>matt</dc:creator>
      <dc:date>2023-07-27T18:40:56Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737074#M2020833</link>
      <description>&lt;P&gt;Thanks Lars,&lt;/P&gt;&lt;P&gt;I am able to generate HASH(Alpha numeric) and wanted to get 6 digit Code like java is producing. Not sure how offset and trunc variable is working. &lt;/P&gt;&lt;P&gt;Any pointer would be helpful.&lt;/P&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;Nikhil&lt;/P&gt;</description>
      <pubDate>Thu, 27 Jul 2023 22:57:40 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737074#M2020833</guid>
      <dc:creator>former_member202253</dc:creator>
      <dc:date>2023-07-27T22:57:40Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737075#M2020834</link>
      <description>&lt;P&gt;Not very difficult to edit your question with menu Actions &amp;gt; Edit, and Ctrl+Shift+V.&lt;/P&gt;&lt;P&gt;So, your Java code:&lt;/P&gt;&lt;PRE&gt;&lt;CODE&gt;package testJavaCode;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.TimeZone;
public class TOTP2 {
	/**
	 * This method converts HEX string to Byte[]
	 * @param hex   the HEX string
	 * @return      A byte array
	 */
	private static byte[] hexStr2Bytes(String hex){
		// Adding one byte to get the right conversion
		// values starting with "0" can be converted
		byte[] bArray = new BigInteger("10" + hex,16).toByteArray();

		// Copy all the REAL bytes, not the "first"
		byte[] ret = new byte[bArray.length - 1];
		for (int i = 0; i &amp;lt; ret.length ; i++)
			ret[i] = bArray[i+1];
		return ret;
	}
	private static final int[] DIGITS_POWER
	// 0 1  2   3    4     5      6       7        8
	= {1,10,100,1000,10000,100000,1000000,10000000,100000000 };
	/**
	 * This method generates an TOTP value for the given
	 * set of parameters.
	 *
	 * @param key   the shared secret, HEX encoded
	 * @param time     a value that reflects a time
	 * @param returnDigits     number of digits to return
	 * @param crypto    the crypto function to use
	 *
	 * @return      A numeric String in base 10 that includes
	 *              {@link truncationDigits} digits
	 * @throws NoSuchAlgorithmException 
	 */
	public static long generateTOTP(byte[] key,
			long timeindex
			) throws Exception {
		SecretKeySpec signkey = new SecretKeySpec(key , "HmacSHA1");
		ByteBuffer bufferobj = ByteBuffer.allocate(8);
		bufferobj.putLong(timeindex);
		byte[] timeBytesobj = bufferobj.array();
		Mac macobj = Mac.getInstance("HmacSHA1");
		macobj.init(signkey);
		byte[] hash = macobj.doFinal(timeBytesobj);
		int offset = hash[19] &amp;amp; 0xf;
		long trunc = hash[offset] &amp;amp; 0x7f;
		for ( int i = 1; i &amp;lt; 4 ; i++)
		{
			trunc &amp;lt;&amp;lt;= 8;
			trunc |= hash[offset + i]  &amp;amp; 0xff;
		}
		return ( trunc %= 1000000 );
	}

	public static void main(String[] args) {
		// Seed for HMAC-SHA1 - 20 bytes
		String seed = "3132333435363738393031323334353637383930";
		// Seed for HMAC-SHA256 - 32 bytes
		long T0 = 0;
		long X = 30;
		try{
				long T = (56344362 - T0)/X;
				System.out.println(generateTOTP(hexStr2Bytes(seed), T));
		}catch (final Exception e){
			System.out.println("Error : " + e);
		}
	}
}
&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Your ABAP code:&lt;/P&gt;&lt;PRE&gt;&lt;CODE&gt;DATA: im_date TYPE sy-datum.
DATA: im_time       TYPE sy-uzeit,
      im_msec       TYPE numc7,
      l_xstring_key TYPE xstring,
      l_key         TYPE string,
      ex_timestamp  TYPE string.
DATA: l_date TYPE sy-datum.
DATA: l_days_timestamp TYPE timestampl.
DATA: l_secs_timestamp TYPE timestampl.
DATA: l_i_days TYPE i.
DATA: l_i_sec TYPE i.
DATA: l_timestamp TYPE timestampl.
DATA: l_dummy TYPE string.
DATA: ts2(25) TYPE c,
      ts      TYPE timestampl.

GET TIME STAMP FIELD ts.
DATA: dat TYPE date,
      tim TYPE time,
      tz  TYPE timezone.
MOVE ts TO ts2.
CONDENSE ts2.
DATA: t1(10),t2(13) TYPE c.
CONVERT TIME STAMP ts TIME ZONE sy-zonlo INTO DATE dat TIME tim.
CONCATENATE dat+0(4) dat+4(2) dat+6(2) INTO t1.
im_date =  dat.
CONCATENATE tim+0(2)  tim+2(2)  tim+4(2)   INTO t2.
im_time = tim.
im_msec = ts2+15(7).
*-----------------------------------------------------------------------
* milliseconds for the days since January 1, 1970, 00:00:00 GMT
* one day has 86400 seconds
l_date = '19700101'.
l_i_days = im_date - l_date.
* timestamp for days past in seconds
l_days_timestamp = l_i_days * 86400.
l_i_sec = im_time.
* timestamp for time at present day
l_secs_timestamp = l_i_sec.
l_timestamp = ( l_days_timestamp + l_secs_timestamp ) * 1000.
ex_timestamp = l_timestamp.
SPLIT ex_timestamp AT '.' INTO ex_timestamp l_dummy.
ex_timestamp = ex_timestamp + im_msec.
SHIFT ex_timestamp RIGHT DELETING TRAILING space.
SHIFT ex_timestamp LEFT DELETING LEADING space.
DATA(l) = ex_timestamp / 1000.
ex_timestamp = round( val = ( ( round( val = l  dec = 0 ) - 0 ) / 30 ) dec = 0 ).
TYPES t_long_int(16) TYPE p DECIMALS 0.
DATA: number TYPE t_long_int,
      result TYPE string.
number = ex_timestamp.
PERFORM convert_base10_to_base16 USING    number
                                 CHANGING result.
WRITE: / number, '--&amp;gt;', result.
TRY.
    l_key  = '3132333435363738393031323334353637383930'.
    l_xstring_key  = cl_abap_hmac=&amp;gt;string_to_xstring( l_key ).
  CATCH cx_abap_message_digest.
ENDTRY.
clear : result.
number = ex_timestamp.
PERFORM  gettotp USING    number
                          l_xstring_key
                          CHANGING result.
  write /       result.

FORM gettotp USING    timeindex TYPE t_long_int
                      key TYPE xstring
                     CHANGING result TYPE string.
CALL METHOD cl_abap_hmac=&amp;gt;get_instance
  EXPORTING
    if_algorithm = 'SHA1'
    if_key       = key
  receiving
    ro_object    = DATA(lo_hmac)  .
data(l_string) = CONV string( timeindex ).
  TRY.
      CALL METHOD lo_hmac-&amp;gt;final
        EXPORTING
          if_data = cl_abap_hmac=&amp;gt;string_to_xstring( l_string  )
      if_offset        = 0
      if_length        = strlen( l_string )
    IMPORTING
      ef_hmacstring    = result  .
    CATCH cx_abap_message_digest .
  ENDTRY.
CALL METHOD lo_hmac-&amp;gt;to_base64
  RECEIVING
    er_hmacb64string = data(l_base)    .
endform.

FORM convert_base10_to_base16 USING    number TYPE t_long_int
                              CHANGING result TYPE string.
  DATA:
    rest  TYPE t_long_int,
    digit TYPE c.
  rest = number MOD 16.
  CASE rest.
    WHEN 0 OR 1 OR 2 OR 3 OR 4 OR 5 OR 6 OR 7 OR 8 OR 9.
      WRITE rest TO digit LEFT-JUSTIFIED NO-SIGN.
    WHEN 10.
      digit = 'A'.
    WHEN 11.
      digit = 'B'.
    WHEN 12.
      digit = 'C'.
    WHEN 13.
      digit = 'D'.
    WHEN 14.
      digit = 'E'.
    WHEN 15.
      digit = 'F'.
  ENDCASE.
  CONCATENATE digit result INTO result.
  rest = number DIV 16.
  IF rest &amp;gt; 0.
    PERFORM convert_base10_to_base16 USING    rest
                                     CHANGING result.
  ENDIF.
ENDFORM.
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Fri, 28 Jul 2023 08:32:30 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737075#M2020834</guid>
      <dc:creator>Sandra_Rossi</dc:creator>
      <dc:date>2023-07-28T08:32:30Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737076#M2020835</link>
      <description>&lt;P&gt;Hi Sandra,&lt;/P&gt;&lt;P&gt;Any advice how to convert Java code to ABAP&lt;/P&gt;&lt;PRE&gt;&lt;CODE&gt;byte[] hash = macobj.doFinal(timeBytesobj);
		int offset = hash[19] &amp;amp; 0xf;
		long trunc = hash[offset] &amp;amp; 0x7f;
		for ( int i = 1; i &amp;lt; 4 ; i++)
		{
			trunc &amp;lt;&amp;lt;= 8;
			trunc |= hash[offset + i]  &amp;amp; 0xff;
		}
		return ( trunc %= 1000000 );&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;Nikhil&lt;/P&gt;</description>
      <pubDate>Mon, 31 Jul 2023 03:33:46 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737076#M2020835</guid>
      <dc:creator>former_member202253</dc:creator>
      <dc:date>2023-07-31T03:33:46Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737077#M2020836</link>
      <description>&lt;P&gt;It seems quite simple to understand. What is your issue?&lt;/P&gt;&lt;P&gt;Equivalences:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&amp;amp; : BIT-AND&lt;/LI&gt;&lt;LI&gt;| : BIT-OR&lt;/LI&gt;&lt;LI&gt;bytestring[ number ] : bytestring+number(1)&lt;/LI&gt;&lt;LI&gt;0xHH : CONSTANTS hh TYPE x LENGTH 1 VALUE 'HH'.&lt;/LI&gt;&lt;LI&gt;&amp;lt;&amp;lt;= 8 : move bits "left" by 8 bits = move 1 byte to the left (CONCATENATE xstring onebyte INTO xstring IN BYTE MODE)&lt;/LI&gt;&lt;LI&gt;% : MOD&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;This code is part of a library, you didn't provide the java code corresponding to it:&lt;/P&gt;&lt;PRE&gt;&lt;CODE&gt;		Mac macobj = Mac.getInstance("HmacSHA1");
		macobj.init(signkey);
		byte[] hash = macobj.doFinal(timeBytesobj);&lt;BR /&gt;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;If it's just SHA-1 calculation, you can use the classic SHA-1 stuff in ABAP.&lt;/P&gt;</description>
      <pubDate>Mon, 31 Jul 2023 05:22:56 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737077#M2020836</guid>
      <dc:creator>Sandra_Rossi</dc:creator>
      <dc:date>2023-07-31T05:22:56Z</dc:date>
    </item>
    <item>
      <title>Re: SAP ABAP: TOTP Generation (Time-based one-time password algorithm)</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737078#M2020837</link>
      <description>&lt;P&gt;Solved by Somnath :https://youtu.be/Ucv-aDfwGRk&lt;/P&gt;</description>
      <pubDate>Wed, 09 Aug 2023 20:17:04 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/sap-abap-totp-generation-time-based-one-time-password-algorithm/m-p/12737078#M2020837</guid>
      <dc:creator>former_member202253</dc:creator>
      <dc:date>2023-08-09T20:17:04Z</dc:date>
    </item>
  </channel>
</rss>

