ABAP RSA 加密
最近出现一些SAP ABAP RSA加密的需求,这里搬运一篇文章,用于学习参考。
本文链接:https://www.cnblogs.com/hhelibeb/p/14952732.html
最近我偶然在SAP社区发现了很多关于RSA加密的未解答的问题。在这里我将尝试提供一些例子,说明如何在ABAP中使用公钥/私钥加密。
所有的间接问题,如证书、信任、撤销和密钥生成,在本文中不会涉及。密钥将用openssl生成。
例子1 – 用自己的ABAP RSA实现
RSA加密是非常简单的。只需要整数算术--主要是模幂运算。唯一的问题是,所涉及的整数比ABAP和大多数其他语言默认能处理的长。幸运的是,这个问题被Harry Boeck用Z04_BIGINTX类解决了,可以在这里找到(出色的工作)。
备注:评论区提到另一个解决方案abapPGP。
生成RSA key
创建一个工作目录,并进入,
mkdir -p /tmp/rsa
cd /tmp/rsa
生成2048位RSA密钥。
/tmp/rsa > openssl genrsa -out rsa.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) .....................................................................+++++ .......+++++ e is 65537 (0x010001)
用纯文本输出公钥和私钥。我们只需要模数(modulus)、公钥指数(publicExponent)和私钥指数(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 . . .
现在有了key和类Z04_BIGINTX,我们可以写程序了。
ABAP程序
在下面的程序中,我们用公钥加密,用私钥签署"Thirty-two bytes secret message!"这个信息。结果显示在屏幕上。它们被保存在生成密钥的相同文件夹中。
签名通常包括对消息进行散列(hash),并对散列值进行签名,但是因为我们的消息足够小,我们跳过散列步骤,直接对消息本身进行签名。作为概念证明,这样做应该是足够的。
实际的工作只是几行代码而已。
加密:
msg_encr_bi = msg_plain_bi->powmod( x = publicExponent
m = pub_modulus_bi ).
签名:
msg_encr_bi = msg_plain_bi->powmod( x = priv_exponent_bi
m = pub_modulus_bi ).
剩下的就是将十六进制转换为十进制,然后再转换回来。
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.
输出如下,
我们看到用公钥指数加密,几乎总是65537,需要约0.2秒,而用私钥指数签名需要30秒。
现在让我们用openssl检查一下结果。
解密,
/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!
添加raw参数,让openssl显示完整消息,
/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!
验证,
/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!
例子2 – 使用CommonCryptoLib
所有RSA的东西都可以用函数组SSFW - SSF Function for Web Services Security轻松完成。除了你可以用openssl中的(-raw)开关得到的东西外,其他的都可以。例如,如果你想使用非标准的padding,这应该是很少见的情况。
为了方便,我将从例1中使用的密钥创建一个PSE并使用该PSE。
在生产中,你可以考虑通过SSFA、STRUST和SSF_GET_PARAMETER来进行。
创建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
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.
运行后,
解密,
/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.
验证,
/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 -
这里我们看到消息的SHA散列值被签名了。
总结
在这里我们学习了如何在ABAP中使用2种不同的方法对短信息进行RSA加密/签名。
1,纯粹的ABAP实现。它在性能(和安全性)上远远比不上CommonCryptoLib。它的意义在于,让我们更好地了解什么是RSA加密。
2,CommonCryptoLib。这里的例子是一个基本的例子。还有很多东西可以做。可能会在下一篇博客中介绍。