Wednesday 14 April 2021

RSA Encryption in ABAP

Recently I stumbled across a lot of unanswered questions about RSA encryption. Here I will try to provides some examples how to use public/private key encryption in ABAP. All the overhead like certificates, trust, revocation and key generation will not be touched here. The keys will be generated with openssl.

Example 1 – Using own RSA implementation  in ABAP.

RSA encryption is quite simple. All you need is integer arithmetic – mainly modular exponentiation. The only problem is, the integers involved are longer than ABAP and most other languages can handle by default. 

Generating the RSA key.

First make a working directory and cd to it.

mkdir -p /tmp/rsa

cd /tmp/rsa

Generate 2048 bit RSA key.

/tmp/rsa > openssl genrsa -out rsa.key 2048

Generating RSA private key, 2048 bit long modulus (2 primes)

.....................................................................+++++

.......+++++

e is 65537 (0x010001)

Print out the key with the public and private components in plain text. We need only the modulus, the publicExponent and the privateExponent.

/tmp/rsa > openssl pkey -in rsa.key -text

-----BEGIN PRIVATE KEY-----

MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDiBbntt4wk807Q

Bzh0gdwwXFyxe1/a41dDZeekgxC5p649B1pT6Ft7P6eSmZqDdZ6t04JpzAdyHjzj

2DMPt6VpAkXyaQSXLHd7dKWYnw2b/akWptd761zx9oIY1tHz0y4VbfkX0yt7FwvP

jUK6XfpcyYymJ1KMmG/UhsIENLxhaU56/gnKdl01XTcKe+JkBpv02dpw+bw6BE34

21FXFmSpoduAHA8/lm+9U6PqdvxU6IDB16n5X74IyUCTQsMW7XQgaw3cqVWTYigU

sZFbHPEddfkCZDNfSodmRd+WZTuCRjD6+K/9+K1j7Kk4a2LMC7r0bPOIYcrW+0VC

+ykiz8QTAgMBAAECggEBAL27/tt+FEhEcymQliS/in6SWkGnBs1xwKRUXEMuvxCK

oWqbzIjZakopIlufVCT8zMqw3i4/1xRGK+k8aYjNKi7feKZI4FCjRF2/iu92vW7w

XkwknIlrB6gavhVp5+9dnLbijZMhcsOukfyWYaifEXdovggQxGw/3siyoxXyyxyd

PSB1Wf+LdZ1EOTaEfk3+lgEpEUzdFTNEC/jwrQJiXzSB+nP5bB0Az3kMcbhxwa01

hAUylXCNtnrRJv0sMvQJOy59gBjiPn3GW62t8Kf/km3IlDRKE7h9xYECafQabaXR

0q6swX09YpdKKBEHYLE9ArpamJtJYPtlA2XSvsfBqkECgYEA84Bt20EpBPldrUFN

GLb7qKNPawRbMff204xx7OtzHD77Th6hcvaXU0C/D4c+DMZNQ/2M4xbLoZWPTOnK

BxOhpbZMH4prxLA4U/6TDQwo9F3kW/1zPcYKfxOgW6tlVHWnLR4Kd1+W7ygNOhjV

El6lWwi008547z05w5ZQ2T+U3OECgYEA7Z+fO6ZWIRqHJq1MCzStTtS+hGkwJArj

DGy8AbvGV7LScmH31sxRJqZp6jHMOICBjgwAPN0VE5eq+xUcPs0p5/seTy/MzSbf

uRG+A//PIG/yUVuOV6nuCYKsY2v2oTUF+v8HGMkfa7WkEhD5S5lZ+oA8gVMXQ4Ey

J235xfPu63MCgYEA4qA+HljX14RK1kw3d/Ad6ocMDDsCsU/qDlvhUDKWcMyBUeSa

OIgesOJKsCYb7wHEuanKrTPzE5FBzMCuQcXYpYUz9gr7YBTuZ+ZAcF1H5J9aQO9z

iSO/cyQOFCNB7MiPbiNOdGmn7S/ml5KzBCTIWyCQQ60fyvG9yDYnSvqtDqECgYBk

29Cxd9us916QKxRQ2U4KXMB04VTep4RRnMF8FuCMDsnGZRDWKijzt8TS88oT3W+g

BDYBn3E3vLOFGSPBAEIeRfdKcyaBmVNycTZu6iBXS0zV/X+AdA8mGEHlfUjUifX8

4Ex517wvcoyuYmf+D5wieFW2KreAHpFULRjMTcqGQwKBgQCMrLoC1dasdvcQ/d9r

sd1AlGjSjoVhGeb19NYQMdOxx29vExP45ClSmnTCTZIZFVpeXHQ4X3ALq2uK4bQp

Cyqrz+4TRLY9e9qgTqNsWkhyke9YSAYNxCb17ZXf7rtHgTJeGbnDvrKC8xa2EvgR

sZknhXCegj6UBsECwPBrYZoDag==

-----END PRIVATE KEY-----

RSA Private-Key: (2048 bit, 2 primes)

modulus:

    00:e2:05:b9:ed:b7:8c:24:f3:4e:d0:07:38:74:81:

    dc:30:5c:5c:b1:7b:5f:da:e3:57:43:65:e7:a4:83:

    10:b9:a7:ae:3d:07:5a:53:e8:5b:7b:3f:a7:92:99:

    9a:83:75:9e:ad:d3:82:69:cc:07:72:1e:3c:e3:d8:

    33:0f:b7:a5:69:02:45:f2:69:04:97:2c:77:7b:74:

    a5:98:9f:0d:9b:fd:a9:16:a6:d7:7b:eb:5c:f1:f6:

    82:18:d6:d1:f3:d3:2e:15:6d:f9:17:d3:2b:7b:17:

    0b:cf:8d:42:ba:5d:fa:5c:c9:8c:a6:27:52:8c:98:

    6f:d4:86:c2:04:34:bc:61:69:4e:7a:fe:09:ca:76:

    5d:35:5d:37:0a:7b:e2:64:06:9b:f4:d9:da:70:f9:

    bc:3a:04:4d:f8:db:51:57:16:64:a9:a1:db:80:1c:

    0f:3f:96:6f:bd:53:a3:ea:76:fc:54:e8:80:c1:d7:

    a9:f9:5f:be:08:c9:40:93:42:c3:16:ed:74:20:6b:

    0d:dc:a9:55:93:62:28:14:b1:91:5b:1c:f1:1d:75:

    f9:02:64:33:5f:4a:87:66:45:df:96:65:3b:82:46:

    30:fa:f8:af:fd:f8:ad:63:ec:a9:38:6b:62:cc:0b:

    ba:f4:6c:f3:88:61:ca:d6:fb:45:42:fb:29:22:cf:

    c4:13

publicExponent: 65537 (0x10001)

privateExponent:

    00:bd:bb:fe:db:7e:14:48:44:73:29:90:96:24:bf:

    8a:7e:92:5a:41:a7:06:cd:71:c0:a4:54:5c:43:2e:

    bf:10:8a:a1:6a:9b:cc:88:d9:6a:4a:29:22:5b:9f:

    54:24:fc:cc:ca:b0:de:2e:3f:d7:14:46:2b:e9:3c:

    69:88:cd:2a:2e:df:78:a6:48:e0:50:a3:44:5d:bf:

    8a:ef:76:bd:6e:f0:5e:4c:24:9c:89:6b:07:a8:1a:

    be:15:69:e7:ef:5d:9c:b6:e2:8d:93:21:72:c3:ae:

    91:fc:96:61:a8:9f:11:77:68:be:08:10:c4:6c:3f:

    de:c8:b2:a3:15:f2:cb:1c:9d:3d:20:75:59:ff:8b:

    75:9d:44:39:36:84:7e:4d:fe:96:01:29:11:4c:dd:

    15:33:44:0b:f8:f0:ad:02:62:5f:34:81:fa:73:f9:

    6c:1d:00:cf:79:0c:71:b8:71:c1:ad:35:84:05:32:

    95:70:8d:b6:7a:d1:26:fd:2c:32:f4:09:3b:2e:7d:

    80:18:e2:3e:7d:c6:5b:ad:ad:f0:a7:ff:92:6d:c8:

    94:34:4a:13:b8:7d:c5:81:02:69:f4:1a:6d:a5:d1:

    d2:ae:ac:c1:7d:3d:62:97:4a:28:11:07:60:b1:3d:

    02:ba:5a:98:9b:49:60:fb:65:03:65:d2:be:c7:c1:

    aa:41

.

.

.

Now with the key and the Z04_BIGINTX class we are ready to write our program.

ABAP program

In the following program we are encrypting with the public key and signing with the private key this message ‘Thirty-two bytes secret message!’. The results are displayed on the screen. They are saved in the same folder where we generated the key to check them outside of SAP. Signing normally involves hashing the message and signing the hash, bus as our message is small enough we skip hashing and sign the message itself. As Proof of Concept should be sufficient.

The actual work is just a couple of lines.

For encryption:

msg_encr_bi = msg_plain_bi->powmod( x = publicExponent

                                    m = pub_modulus_bi ).

and for signing:

msg_encr_bi = msg_plain_bi->powmod( x = priv_exponent_bi

                                    m = pub_modulus_bi ).

The rest is converting from hex to decimal and back.

REPORT Z_RSA.

data: bi1     type ref to z04_BigIntX,

      bi2     type ref to z04_BigIntX,

      bi256   type ref to z04_BigIntX,

      s  type string,

      i1 type I,

      i2 type I,

      i3 type I value 0,

      x1 type X,

      publicExponent   type ref to z04_BigIntX,

      pub_modulus_s    type string,

      pub_modulus_x    type xstring,

      pub_modulus_bi   type ref to z04_BigIntX,

      priv_exponent_s  type string,

      priv_exponent_x  type xstring,

      priv_exponent_bi type ref to z04_BigIntX,

      msg_text         type string,

      msg_plain_bi     type ref to z04_BigIntX,

      msg_encr_bi      type ref to z04_BigIntX,

      msg_encr_x       type xstring,

      msg_sign_x       type xstring,

      pkcs_rnd         type xstring,

      pkcs_ff_s        type string,

      pkcs_ff_x        type xstring,

      pkcs_head_sign   type xstring value '0001',

      pkcs_head_encr   type xstring value '0002',

      pkcs_zero        type xstring value '00',

      pkcs_one         type xstring value '01',

      msg_xstr         type xstring,

      msg_xstr_e       type xstring,

      msg_xstr_s       type xstring,

      msg_file_name    type string value '/tmp/rsa/encrypted_msg',

      msg_file_name_s  type string value '/tmp/rsa/signed_msg'.

create object msg_plain_bi.

create object bi1.

create object bi2.

create object bi256.

create object publicExponent.

create object pub_modulus_bi.

create object priv_exponent_bi.

create object msg_encr_bi.

DATA: T1 TYPE I, T2 TYPE I, T3 TYPE I.

bi256->seti( 256 ).

*---------------------

* PREPARE THE KEY

*---------------------

" public exponent

publicExponent->setstr( '65537' ).

" private exponent

CONCATENATE

  '00:bd:bb:fe:db:7e:14:48:44:73:29:90:96:24:bf:'

  '8a:7e:92:5a:41:a7:06:cd:71:c0:a4:54:5c:43:2e:'

  'bf:10:8a:a1:6a:9b:cc:88:d9:6a:4a:29:22:5b:9f:'

  '54:24:fc:cc:ca:b0:de:2e:3f:d7:14:46:2b:e9:3c:'

  '69:88:cd:2a:2e:df:78:a6:48:e0:50:a3:44:5d:bf:'

  '8a:ef:76:bd:6e:f0:5e:4c:24:9c:89:6b:07:a8:1a:'

  'be:15:69:e7:ef:5d:9c:b6:e2:8d:93:21:72:c3:ae:'

  '91:fc:96:61:a8:9f:11:77:68:be:08:10:c4:6c:3f:'

  'de:c8:b2:a3:15:f2:cb:1c:9d:3d:20:75:59:ff:8b:'

  '75:9d:44:39:36:84:7e:4d:fe:96:01:29:11:4c:dd:'

  '15:33:44:0b:f8:f0:ad:02:62:5f:34:81:fa:73:f9:'

  '6c:1d:00:cf:79:0c:71:b8:71:c1:ad:35:84:05:32:'

  '95:70:8d:b6:7a:d1:26:fd:2c:32:f4:09:3b:2e:7d:'

  '80:18:e2:3e:7d:c6:5b:ad:ad:f0:a7:ff:92:6d:c8:'

  '94:34:4a:13:b8:7d:c5:81:02:69:f4:1a:6d:a5:d1:'

  'd2:ae:ac:c1:7d:3d:62:97:4a:28:11:07:60:b1:3d:'

  '02:ba:5a:98:9b:49:60:fb:65:03:65:d2:be:c7:c1:'

  'aa:41'

into priv_exponent_s.

replace ALL OCCURRENCES OF REGEX '(:)' in priv_exponent_s with ''.

TRANSLATE priv_exponent_s TO UPPER CASE.

priv_exponent_x = priv_exponent_s.

" Convert the modulus from HEX to DEC

bi2->seti( 1 ).

i1 = xstrlen( priv_exponent_x ).

WHILE ( i1 > 0 ).

  i1 = i1 - 1.

  i2 = priv_exponent_x+i1(1).

  bi1->seti( i2 ).

  bi1->mul( bi2 ).

  bi2->mul( bi256 ).

  priv_exponent_bi = priv_exponent_bi->add( bi1 ).

ENDWHILE.


" public key

CONCATENATE

  '00:e2:05:b9:ed:b7:8c:24:f3:4e:d0:07:38:74:81:'

  'dc:30:5c:5c:b1:7b:5f:da:e3:57:43:65:e7:a4:83:'

  '10:b9:a7:ae:3d:07:5a:53:e8:5b:7b:3f:a7:92:99:'

  '9a:83:75:9e:ad:d3:82:69:cc:07:72:1e:3c:e3:d8:'

  '33:0f:b7:a5:69:02:45:f2:69:04:97:2c:77:7b:74:'

  'a5:98:9f:0d:9b:fd:a9:16:a6:d7:7b:eb:5c:f1:f6:'

  '82:18:d6:d1:f3:d3:2e:15:6d:f9:17:d3:2b:7b:17:'

  '0b:cf:8d:42:ba:5d:fa:5c:c9:8c:a6:27:52:8c:98:'

  '6f:d4:86:c2:04:34:bc:61:69:4e:7a:fe:09:ca:76:'

  '5d:35:5d:37:0a:7b:e2:64:06:9b:f4:d9:da:70:f9:'

  'bc:3a:04:4d:f8:db:51:57:16:64:a9:a1:db:80:1c:'

  '0f:3f:96:6f:bd:53:a3:ea:76:fc:54:e8:80:c1:d7:'

  'a9:f9:5f:be:08:c9:40:93:42:c3:16:ed:74:20:6b:'

  '0d:dc:a9:55:93:62:28:14:b1:91:5b:1c:f1:1d:75:'

  'f9:02:64:33:5f:4a:87:66:45:df:96:65:3b:82:46:'

  '30:fa:f8:af:fd:f8:ad:63:ec:a9:38:6b:62:cc:0b:'

  'ba:f4:6c:f3:88:61:ca:d6:fb:45:42:fb:29:22:cf:'

  'c4:13'

into pub_modulus_s.

replace ALL OCCURRENCES OF REGEX '(:)' in pub_modulus_s with ''.

TRANSLATE pub_modulus_s TO UPPER CASE.

pub_modulus_x = pub_modulus_s.

" Convert the modulus from HEX to DEC

bi2->seti( 1 ).

i1 = xstrlen( pub_modulus_x ).

WHILE ( i1 > 0 ).

  i1 = i1 - 1.

  i2 = pub_modulus_x+i1(1).

  bi1->seti( i2 ).

  bi1->mul( bi2 ).

  bi2->mul( bi256 ).

  pub_modulus_bi = pub_modulus_bi->add( bi1 ).

ENDWHILE.

*---------------------

* END PREPARE THE KEY

*---------------------

msg_text = 'Thirty-two bytes secret message!'.

write: / 'Plain message:'.

write: / msg_text.

SKIP.

*---------------------

* START ENCRYPTION

*---------------------

CALL FUNCTION 'SCMS_STRING_TO_XSTRING'

  EXPORTING

    text = msg_text

  IMPORTING

    buffer = msg_xstr.

write: / 'Plain message in HEX:'.

PERFORM SHOW_DATA USING msg_xstr.

SKIP.

i1 = 256 - 3 - xstrlen( msg_xstr ).

CALL FUNCTION 'GENERATE_SEC_RANDOM'

  EXPORTING

    length = i1

  IMPORTING

    random = pkcs_rnd

  EXCEPTIONS

    INVALID_LENGTH = 1

    NO_MEMORY = 2

    INTERNAL_ERROR = 3.

  do i1 TIMES.

    CONCATENATE 'FF' pkcs_ff_s INTO pkcs_ff_s.

  enddo.

  pkcs_ff_x = pkcs_ff_s.

REPLACE ALL OCCURRENCES OF pkcs_zero in pkcs_rnd with pkcs_one IN BYTE MODE.

CONCATENATE

 pkcs_head_encr

 pkcs_rnd

 pkcs_zero

 msg_xstr

into msg_xstr_e in byte mode.

write: / 'Plain message PKCS1-V1.5 padded for encryption in HEX:'.

PERFORM SHOW_DATA USING msg_xstr_e.

SKIP.

" Convert the padded plain text message from HEX to DEC

i1 = xstrlen( msg_xstr_e ).

bi2->seti( 1 ).

WHILE ( i1 > 0 ).

  i1 = i1 - 1.

  i2 = msg_xstr_e+i1(1).

  bi1->seti( i2 ).

  bi1->mul( bi2 ).

  bi2->mul( bi256 ).

  msg_plain_bi = msg_plain_bi->add( bi1 ).

ENDWHILE.

" Encrypt the message

GET RUN TIME FIELD T1.

msg_encr_bi = msg_plain_bi->powmod( x = publicExponent

                                    m = pub_modulus_bi ).

GET RUN TIME FIELD T2.

T3 = T2 - T1.

write: / 'Encryption time:', T3.

" Convert the encrypted message from DEC to HEX

WHILE ( s <> '0' ).

  i1 = bi2->setobj( msg_encr_bi )->mod( bi256 )->getstr( 0 ) + i3.

  if i1 = 256.

     i3 = 1.

  else.

     i3 = 0.

  endif.

  x1 = i1.

  s = msg_encr_bi->div( bi256 )->getstr( 0 ).

  CONCATENATE x1 msg_encr_x INTO msg_encr_x IN BYTE MODE.

ENDWHILE.

" output encrypted message

OPEN DATASET msg_file_name FOR OUTPUT IN BINARY MODE.

TRANSFER msg_encr_x TO msg_file_name.

CLOSE DATASET msg_file_name.

write: / 'RSA encrypted message:'.

PERFORM SHOW_DATA USING msg_encr_x.

SKIP.

*---------------------

* END ENCRYPTION

*---------------------

*---------------------

* START SIGNING

*---------------------

" Message PKCS#1 padding for signing

CONCATENATE

 pkcs_head_sign

 pkcs_ff_x

 pkcs_zero

 msg_xstr

into msg_xstr_s in byte mode.

write: / 'Plain message PKCS1-V1.5 padded for signing in HEX:'.

PERFORM SHOW_DATA USING msg_xstr_s.

SKIP.

" Convert the padded plain text message from HEX to DEC

msg_plain_bi->seti( 0 ).

i1 = xstrlen( msg_xstr_s ).

bi2->seti( 1 ).

WHILE ( i1 > 0 ).

  i1 = i1 - 1.

  i2 = msg_xstr_s+i1(1).

  bi1->seti( i2 ).

  bi1->mul( bi2 ).

  bi2->mul( bi256 ).

  msg_plain_bi = msg_plain_bi->add( bi1 ).

ENDWHILE.

" Sign the message

GET RUN TIME FIELD T1.

msg_encr_bi = msg_plain_bi->powmod( x = priv_exponent_bi

                                    m = pub_modulus_bi ).

GET RUN TIME FIELD T2.

i1 = T2 - T1.

write: / 'Signing time:', i1.

s = ''.

msg_sign_x = ''.

" Convert the encrypted message from DEC to HEX

WHILE ( s <> '0' ).

  i1 = bi2->setobj( msg_encr_bi )->mod( bi256 )->getstr( 0 ) + i3.

  if i1 = 256.

     i3 = 1.

  else.

     i3 = 0.

  endif.

  x1 = i1.

  s = msg_encr_bi->div( bi256 )->getstr( 0 ).

  CONCATENATE x1 msg_sign_x INTO msg_sign_x IN BYTE MODE.

ENDWHILE.

" Output signed message

OPEN DATASET msg_file_name_s FOR OUTPUT IN BINARY MODE.

TRANSFER msg_sign_x TO msg_file_name_s.

CLOSE DATASET msg_file_name_s.

write: / 'RSA signed message:'.

PERFORM SHOW_DATA USING msg_sign_x.

*---------------------

* END SIGNING

*---------------------

FORM SHOW_DATA USING  data_x TYPE xstring.

  DATA: data_len TYPE I

      , i1       TYPE I value 0

      , i2       TYPE I value 32.

  data_len = xstrlen( data_x ).

  WHILE ( i1 < data_len ).

    i2 = nmin( val1 = i2

               val2 = data_len ).

    WRITE: / data_x+i1(i2).

    i1 = i1 + 32.

  ENDWHILE.

ENDFORM.

Here the output.

SAP ABAP Exam Prep, SAP ABAP Preparation, SAP ABAP Career, SAP ABAP Study Materials

We see encryption with the public exponent, which is almost always 65537, takes ~0.2 seconds where signing with the private exponent takes 30 seconds.

Let’s now check the results with openssl.

Decrypt.

/tmp/rsa >xxd encrypted_msg

00000000: dd64 ff4c f19e 6274 b3fd aa8b ecc2 9fe0  .d.L..bt........

00000010: 6d87 760f 1239 d01f 81ce e53b 3587 f601  m.v..9.....;5...

00000020: 8e03 4099 a582 bbdd e45b 7cf7 be79 76b9  ..@......[|..yv.

00000030: 7068 3cd5 2b72 a7d6 2c51 e805 36d3 3eb8  ph<.+r..,Q..6.>.

00000040: c11c 4584 01f3 3bfd d265 1bf7 aff1 d97a  ..E...;..e.....z

00000050: aded 0b4a b59d 3c3c 4675 e38d 8409 aedc  ...J..<<Fu......

00000060: 1242 b562 5ced 9662 c9f3 5974 4cc3 3227  .B.b\..b..YtL.2'

00000070: b750 6cea e244 892b 873f 32e7 c4fd 4f78  .Pl..D.+.?2...Ox

00000080: 6a5e 7063 d0fe c5ef 9219 8549 b025 47c9  j^pc.......I.%G.

00000090: 0b3a 5598 d780 aab4 ab5a 6bb0 8ba5 f822  .:U......Zk...."

000000a0: 735f 2b43 68e6 5630 9c90 1712 6196 6d06  s_+Ch.V0....a.m.

000000b0: e2fc 87c1 db42 554f 3688 929a 6550 5173  .....BUO6...ePQs

000000c0: b951 30f6 ca5b a60a 2cc7 5710 915a 2809  .Q0..[..,.W..Z(.

000000d0: c6d8 60ba 3eac bcc1 9814 cc6a e777 757f  ..`.>......j.wu.

000000e0: 44ae ce00 3869 a275 4c4b 3f8e e5e2 eb67  D...8i.uLK?....g

000000f0: 34ac 13cb f89e 5edc 9d67 d5e8 704e d9c6  4.....^..g..pN..

/tmp/rsa >

/tmp/rsa >openssl rsautl -decrypt -in encrypted_msg -inkey rsa.key | xxd

00000000: 5468 6972 7479 2d74 776f 2062 7974 6573  Thirty-two bytes

00000010: 2073 6563 7265 7420 6d65 7373 6167 6521   secret message!

Adding -raw to openssl displays the whole message

/tmp/rsa >openssl rsautl -decrypt -in encrypted_msg -inkey rsa.key -raw | xxd

00000000: 0002 4316 8cf2 e289 8dc4 67cf be1b f547  ..C.......g....G

00000010: ae0b b98b 8ef8 79ba 9b98 ac20 3660 d6ac  ......y.... 6`..

00000020: 3330 e613 752c a9ab 3f88 368b 223b 050b  30..u,..?.6.";..

00000030: b79d 40c2 2ef9 9de9 e363 10d1 199b 97f0  ..@......c......

00000040: 33da b96d e3fc 62d6 06c4 ebb5 3ee2 b823  3..m..b.....>..#

00000050: 4f22 d924 ac1d dd89 0215 889f 4c1f 9364  O".$........L..d

00000060: 1220 81bd 21d7 1dd2 280e d74a 4024 99ae  . ..!...(..J@$..

00000070: a8ed 3fad 30aa e281 db4c 5454 c237 9bc0  ..?.0....LTT.7..

00000080: 9338 2a39 197b 9972 4c11 b260 7f31 e407  .8*9.{.rL..`.1..

00000090: 81ea 2be7 a9da 336b 6b66 8bde 1774 3bd0  ..+...3kkf...t;.

000000a0: 0ccd 3b93 983c 1c51 b32d a31b 06f6 533e  ..;..<.Q.-....S>

000000b0: 144a 1c2a f32d 875f 4873 8b41 dcc7 8b18  .J.*.-._Hs.A....

000000c0: 40e4 4414 bd7e c49a 5282 b165 3698 fdf6  @.D..~..R..e6...

000000d0: 9e20 b83b 3185 c7ee 962a 9bb5 f173 8900  . .;1....*...s..

000000e0: 5468 6972 7479 2d74 776f 2062 7974 6573  Thirty-two bytes

000000f0: 2073 6563 7265 7420 6d65 7373 6167 6521   secret message!

Verify.

/tmp/rsa >xxd signed_msg

00000000: d540 f2b5 1e7e bb83 aa6e d099 1ad6 ee1e  .@...~...n......

00000010: ccdb ffaf e579 0e98 323e b055 7164 4b71  .....y..2>.UqdKq

00000020: a71c 0e6e 5e74 3fdb c914 97ac e063 8ece  ...n^t?......c..

00000030: 086e d8ac fad9 14a7 7f47 bd34 22a9 d0ab  .n.......G.4"...

00000040: 73e7 80fc 65af fbd7 d3df 7672 1d31 88e7  s...e.....vr.1..

00000050: b489 311c eb36 25bf 3e8b 4efb b97c df96  ..1..6%.>.N..|..

00000060: 5440 165b a820 514d 9649 531f 402c 5767  T@.[. QM.IS.@,Wg

00000070: 508c adeb 1954 e14f e2ce d64e ba30 0c4a  P....T.O...N.0.J

00000080: aeca 0927 7823 9bc6 0083 99f7 e605 ae9d  ...'x#..........

00000090: 2cd9 205e 41f4 1587 5b3f 1574 047d 42b3  ,. ^A...[?.t.}B.

000000a0: 6e5a a74b cfaa fde5 4d09 26f9 82ca f1b5  nZ.K....M.&.....

000000b0: 9299 f2df 7444 472d 1554 3378 c544 7f20  ....tDG-.T3x.D.

000000c0: b6b0 80be a241 2d24 c561 da69 522d 86db  .....A-$.a.iR-..

000000d0: 2388 cbe5 15fe 9967 3bbd 36f5 5a70 8a05  #......g;.6.Zp..

000000e0: a30c 2c89 2f05 b470 15d3 482f e53b 947a  ..,./..p..H/.;.z

000000f0: c7f5 feba bd41 a877 750e c9f8 cb7a c7b1  .....A.wu....z..

/tmp/rsa >

/tmp/rsa >openssl rsautl -verify -in signed_msg -inkey rsa.key | xxd

00000000: 5468 6972 7479 2d74 776f 2062 7974 6573  Thirty-two bytes

00000010: 2073 6563 7265 7420 6d65 7373 6167 6521   secret message!

/tmp/rsa >

/tmp/rsa >openssl rsautl -verify -in signed_msg -inkey rsa.key -raw | xxd

00000000: 0001 ffff ffff ffff ffff ffff ffff ffff  ................

00000010: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000020: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000030: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000040: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000050: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000060: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000070: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................

000000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................

000000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................

000000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ................

000000d0: ffff ffff ffff ffff ffff ffff ffff ff00  ................

000000e0: 5468 6972 7479 2d74 776f 2062 7974 6573  Thirty-two bytes

000000f0: 2073 6563 7265 7420 6d65 7373 6167 6521   secret message!

Example 2 – Using CommonCryptoLib

All RSA stuff can be done easily with Function group SSFW – SSF Functions for Web Services Security. All except what you can get with the (-raw) switch in openssl. For example if you want to use non-standard padding, bit this should be rarely the case.

To make my life easy I will create a PSE from the key used in Example 1 and use that PSE.

In production you may consider to do it right through SSFA, STRUST and SSF_GET_PARAMETER.

Create the PSE.

/tmp/rsa > openssl req -x509 -sha256 -key rsa.key -out user1.cer -days 3650 -subj '/CN=user1'

/tmp/rsa > openssl pkcs12 -export -inkey rsa.key -in user1.cer -out user1.pfx -nodes

Enter Export Password:

Verifying - Enter Export Password:

/tmp/rsa > setenv SECUDIR $PWD

/tmp/rsa > sapgenpse import_p12 -x "" -p user1.pse user1.pfx

Found key 'INDEX=0,SIG=YES,ENC=YES,MD5-FINGERPRINT=3B9E 77DD E5E4 3371 19FA 2FCF D1CA 512F,KEYID=3D1E2BC7E33500A3D2A098B63FE9962A6B63318C'

!!! WARNING: For security reasons it is recommended to use a PIN/passphrase

!!! WARNING: which is at least 8 characters long and contains characters in

!!! WARNING: upper and lower case, numbers and non-alphanumeric symbols.

PSE "/tmp/rsa/user1.pse" was written

Move to ABAP

REPORT Z_RSA_CCL.

DATA: lf_output        TYPE xstring.

DATA: lf_plain_input_x TYPE xstring.

DATA: lf_plain_input   TYPE string.

DATA: msg_file_name    TYPE STRING.

DATA: T1 TYPE I, T2 TYPE I, T3 TYPE I.

lf_plain_input = 'Thirty-two bytes secret message.'.

CALL FUNCTION 'SCMS_STRING_TO_XSTRING'

  EXPORTING

      text = lf_plain_input

  IMPORTING

    buffer = lf_plain_input_x.

DATA: it_recipient_list   TYPE STANDARD TABLE OF ssfinfo,

      wa_recipient_list   LIKE LINE OF it_recipient_list.

wa_recipient_list-id = 'CN=user1'.

APPEND wa_recipient_list TO it_recipient_list.

GET RUN TIME FIELD T1.

CALL FUNCTION 'SSFW_KRN_ENVELOPE'

  EXPORTING

    STR_FORMAT       = 'PKCS1-V1.5'

    STR_PAB          = '/tmp/rsa/user1.pse'

    ostr_input_data  = lf_plain_input_x

  IMPORTING

     OSTR_ENVELOPED_DATA = lf_output

  TABLES

      RECIPIENT_LIST = it_recipient_list

  EXCEPTIONS

      OTHERS = 1.

GET RUN TIME FIELD T2.

T3 = T2 - T1.

write: / 'Encryption time:', T3.

msg_file_name = '/tmp/rsa/ccl_encrypted_msg'.

OPEN DATASET msg_file_name FOR OUTPUT IN BINARY MODE.

TRANSFER lf_output TO msg_file_name.

CLOSE DATASET msg_file_name.

write: / 'RSA CCL encrypted message:'.

PERFORM SHOW_DATA USING lf_output.

skip.

DATA: lf_signer          TYPE ssfinfo.

DATA: lt_signer TYPE STANDARD TABLE OF ssfinfo." WITH HEADER LINE.

lf_signer-id = 'CN=user1'.

lf_signer-profile = '/tmp/rsa/user1.pse'.

APPEND lf_signer TO lt_signer.

GET RUN TIME FIELD T1.

CALL FUNCTION 'SSFW_KRN_SIGN'

  EXPORTING

    str_format       = 'PKCS1-V1.5'

    str_chainfmt     = 'X509v3'

    STR_HASHALG      = 'SHA256'

    ostr_input_data  = lf_plain_input_x

  IMPORTING

    ostr_signed_data = lf_output

  TABLES

    signer           = lt_signer

  EXCEPTIONS

    OTHERS =              1.

GET RUN TIME FIELD T2.

T3 = T2 - T1.

write: / 'Signing time:', T3.

msg_file_name = '/tmp/rsa/ccl_signed_msg'.

OPEN DATASET msg_file_name FOR OUTPUT IN BINARY MODE.

TRANSFER lf_output TO msg_file_name.

CLOSE DATASET msg_file_name.

write: / 'RSA CCL signed message:'.

PERFORM SHOW_DATA USING lf_output.

FORM SHOW_DATA USING  data_x TYPE xstring.

  DATA: data_len TYPE I

      , i1       TYPE I value 0

      , i2       TYPE I value 32.

  data_len = xstrlen( data_x ).

  WHILE ( i1 < data_len ).

    i2 = nmin( val1 = i2

               val2 = data_len ).

    WRITE: / data_x+i1(i2).

    i1 = i1 + 32.

  ENDWHILE.

ENDFORM.

After execution.

SAP ABAP Exam Prep, SAP ABAP Preparation, SAP ABAP Career, SAP ABAP Study Materials

Check it with openssl again

Decrypt.

/tmp/rsa > xxd ccl_encrypted_msg

00000000: 3c5b 4c97 0c5c 0e68 1f84 7ced 4f01 e11c  <[L..\.h..|.O...

00000010: 3bce b761 a03e ad15 2f9d 5836 f187 1e44  ;..a.>../.X6...D

00000020: ca71 7cfb 84ef 0b2d 2203 fe6a 502e f065  .q|....-"..jP..e

00000030: 9790 c4cd 8164 912b 8b13 926b 4537 b953  .....d.+...kE7.S

00000040: a3d1 1f15 0919 ccf4 d3af 9e2b 6bfb 7e61  ...........+k.~a

00000050: 1f25 6d70 c9d5 c48e b38b aa6c 5300 d22b  .%mp.......lS..+

00000060: aaac e4b5 6dc5 cb66 39a2 86e2 a41d 96ab  ....m..f9.......

00000070: 6901 ade9 8a17 74df 8237 a963 73a4 4da9  i.....t..7.cs.M.

00000080: bf13 7be2 704a fc8c 8889 1fad 279e 6397  ..{.pJ......'.c.

00000090: 2d13 d0d1 22a2 c0de 8c72 b12f bd90 31ec  -..."....r./..1.

000000a0: ef98 0a7f f971 5f71 4a9f 4060 0715 4c40  .....q_qJ.@`..L@

000000b0: 1397 09c8 333b df8a 3243 2db3 c276 d875  ....3;..2C-..v.u

000000c0: 6cad 5dcb af41 f00c 2cad 4053 da72 158c  l.]..A..,.@S.r..

000000d0: ac67 52ad 6940 8049 4c3c 727a a19e a513  .gR.i@.IL<rz....

000000e0: 716d a4eb 0826 07c4 1624 307f 68d6 3014  qm...&...$0.h.0.

000000f0: 43ec 2cb8 ea44 2868 1a24 e1aa 594b e646  C.,..D(h.$..YK.F

/tmp/rsa > openssl rsautl -decrypt -in ccl_encrypted_msg -inkey rsa.key | xxd

00000000: 5468 6972 7479 2d74 776f 2062 7974 6573  Thirty-two bytes

00000010: 2073 6563 7265 7420 6d65 7373 6167 652e   secret message.

/tmp/rsa > openssl rsautl -decrypt -in ccl_encrypted_msg -inkey rsa.key -raw | xxd

00000000: 0002 da46 9aee 3bb8 53e7 9ecf 99a0 0a60  ...F..;.S......`

00000010: e8cc 89e5 56ad 4c10 d2a5 6a62 6612 068e  ....V.L...jbf...

00000020: 9f7a e956 4325 0b32 7e75 457a ac75 639c  .z.VC%.2~uEz.uc.

00000030: 64a5 17b7 5c1c 721a d2d3 1a2b 1770 0a73  d...\.r....+.p.s

00000040: ccec 5802 66b7 d2e3 2f96 11bd 6708 2d3d  ..X.f.../...g.-=

00000050: 298c 76ce 02f9 7b84 4a36 911b 81ad d047  ).v...{.J6.....G

00000060: 5452 6e64 2d0d f55a c048 9f13 2aef ff70  TRnd-..Z.H..*..p

00000070: ff2d 7c5d 0162 a8d0 82d2 5c64 bf3c e380  .-|].b....\d.<..

00000080: b93d 4d98 a1b6 164c 8ded 016d ad94 9fd2  .=M....L...m....

00000090: 7632 e64c 080f 7728 5817 0f50 1d9c cfd3  v2.L..w(X..P....

000000a0: f67e 5ccb eafb 9cc9 9916 4bd4 c64e 1494  .~\.......K..N..

000000b0: f47f e38e 33f4 2121 91df d9f9 7233 f182  ....3.!!....r3..

000000c0: 2008 bb21 654d 0fd3 482d da42 8cfb b4c1   ..!eM..H-.B....

000000d0: a267 78ae e55e cde5 1f8d e3e6 d5df 1000  .gx..^..........

000000e0: 5468 6972 7479 2d74 776f 2062 7974 6573  Thirty-two bytes

000000f0: 2073 6563 7265 7420 6d65 7373 6167 652e   secret message.

Verify.

/tmp/rsa > xxd ccl_signed_msg

00000000: 9e8f 2678 2ed6 3d6d ae74 16f6 4101 75ed  ..&x..=m.t..A.u.

00000010: 3fd0 d962 7f2b 7d46 f3b7 8097 7411 37f3  ?..b.+}F....t.7.

00000020: 89c6 e3fc 81b7 93a6 7814 020b 9b3a 8ebd  ........x....:..

00000030: 9e9f 3549 e521 a7ff 27ef aef5 10f5 dada  ..5I.!..'.......

00000040: e2cb f6b9 8cf4 c663 43f2 98d7 2127 040d  .......cC...!'..

00000050: 6b4e 7c23 bad7 db40 7442 9c4d d6b4 b0f9  kN|#...@tB.M....

00000060: 2e35 5500 1499 c938 536f 6763 99b5 895b  .5U....8Sogc...[

00000070: 2b57 5b81 f757 ffee f7fa dc8c b447 afd8  +W[..W.......G..

00000080: 1630 ac6f 5621 8fc1 c3ab ed7f 1893 3b91  .0.oV!........;.

00000090: 9575 055c 7a9e 6a76 b5ce 000e 5ab2 3eae  .u.\z.jv....Z.>.

000000a0: 5574 2a8e f0fa 3f2e 9897 2c95 4e64 16bc  Ut*...?...,.Nd..

000000b0: 0040 00fd 3202 d458 8c1f 45da 7f1c f238  .@..2..X..E....8

000000c0: 8e68 0dc1 b692 d1bb 48c2 2f0d a429 eaa8  .h......H./..)..

000000d0: b962 05ba 0a7b b246 7719 1406 5649 0681  .b...{.Fw...VI..

000000e0: fae5 dadd 7946 1775 5e2d eff7 2d95 993a  ....yF.u^-..-..:

000000f0: 9a6f 4e7b 0770 b887 b34f 271a 43af 8e68  .oN{.p...O'.C..h

/tmp/rsa > openssl rsautl -verify -in ccl_signed_msg -inkey rsa.key | xxd

00000000: 3031 300d 0609 6086 4801 6503 0402 0105  010...`.H.e.....

00000010: 0004 20c0 4726 d78a 7628 27e3 dffe 9f42  .. .G&..v('....B

00000020: c2fe e624 7a2e 59f7 a0c9 85ef 7728 a5d4  ...$z.Y.....w(..

00000030: a106 8f                                  ...

/tmp/rsa > openssl rsautl -verify -in ccl_signed_msg -inkey rsa.key -raw | xxd

00000000: 0001 ffff ffff ffff ffff ffff ffff ffff  ................

00000010: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000020: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000030: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000040: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000050: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000060: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000070: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................

00000090: ffff ffff ffff ffff ffff ffff ffff ffff  ................

000000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ................

000000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ................

000000c0: ffff ffff ffff ffff ffff ffff 0030 3130  .............010

000000d0: 0d06 0960 8648 0165 0304 0201 0500 0420  ...`.H.e.......

000000e0: c047 26d7 8a76 2827 e3df fe9f 42c2 fee6  .G&..v('....B...

000000f0: 247a 2e59 f7a0 c985 ef77 28a5 d4a1 068f  $z.Y.....w(.....

/tmp/rsa > echo -n 'Thirty-two bytes secret message.' | sha256sum

c04726d78a762827e3dffe9f42c2fee6247a2e59f7a0c985ef7728a5d4a1068f  -

Here we see the SHA hash of the message is signed.

No comments:

Post a Comment