ABAP RSA加密实现(加解密及签名)

43 篇文章 7 订阅

目录

一、使用标准函数实现

RSA加密示例-使用公钥字符串加密

RSA加密示例-通过PSE证书文件加密

RSA解密示例-通过PSE证书文件解密

RSA签名验签示例-使用证书签名验签

密钥

参考

注意事项

二、openssl命令行实现

示例代码

SM69配置

参考

三、开源代码实现


一、使用标准函数实现

         Pakage SECF 下的函数组SSFW SSF Functions for Web Services Security

  • RSA加密示例-使用公钥字符串加密

DATA: lv_output         TYPE xstring,
      lv_input_x        TYPE xstring,
      lv_input          TYPE string,
      lv_crc            TYPE ssfparms-ssfcrc,
      lt_recipient_list TYPE STANDARD TABLE OF ssfinfo,
      ls_recipient_list LIKE LINE OF lt_recipient_list.

DATA: lv_base64    TYPE string,
      lv_pubkey    TYPE xstring,
      lv_pubbase64 TYPE string,
      lv_str       TYPE string.

lv_input = '待加密字符串'.

lv_input_x = cl_bcs_convert=>string_to_xstring( lv_input ).

" 加密
lv_pubbase64 = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0QgZrYkLPNredTBg9QtD'
            && 'z780aBQNW1ACwF84Sz/Q7aBiaiqSwLmSez6zhdZK4g7LRWkbb4VvadoVglnbzqDh'
            && 'JI0qeEh/YEUWp0mhYMw2c00wKB0ZWEZAevi+h9i8OhzAAnKB30eDqDIvfhSCkqmp'
            && 'TII/fqNwq0H5vXfwbiPAHEgdKHQtirZZx9fhaEN9/gfKc+sprjEMeZla/PphbkEW'
            && 'JnoN44uECrHghR72BLXrAZtkEk86ZfUSh1JuPjamKvX9qJiyTxxNPyC9+wjBn4+R'
            && 'J0yUvpcIrJ5jmdeogvorZe5DsdjoVNAA4u7c/YWpaq33O8491MyENoJUqMZde9AO'
            && 'RwIDAQAB'.

CALL FUNCTION 'SCMS_BASE64_DECODE_STR'
  EXPORTING
    input  = lv_pubbase64
*   UNESCAPE       = 'X'
  IMPORTING
    output = lv_pubkey
  EXCEPTIONS
    failed = 1
    OTHERS = 2.

" 模数 参考加密概述
lv_str = lv_pubkey.
DATA(length) = strlen( lv_str ).
IF length > 514." 2048位密钥
  DATA(pos) = length - 10 - 514.
  lv_str = lv_str+pos(514).
ELSEIF length > 256." 1024位密钥
  pos = length - 10 - 256.
  lv_str = lv_str+pos(256).
ENDIF.

" 函数使用密钥格式
lv_str = 'R:m=' && lv_str && ':e=010001:'.
lv_pubkey = cl_bcs_convert=>string_to_xstring( lv_str ).

 ls_recipient_list-id = '<implicit>'."
 APPEND ls_recipient_list TO lt_recipient_list.
 
CALL FUNCTION 'SSFW_KRN_ENVELOPE'
  EXPORTING
    str_format          = 'PKCS1-V1.5'
    str_pab             = '<no_certificate_check>'
    str_chainfmt        = 'KEYVALUE'
    ostr_chain_data     = lv_pubkey
    ostr_input_data     = lv_input_x
  IMPORTING
    ostr_enveloped_data = lv_output
    crc                 = lv_crc
  TABLES
    recipient_list      = lt_recipient_list
  EXCEPTIONS
    OTHERS              = 1.

CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
  EXPORTING
    input  = lv_output
  IMPORTING
    output = lv_base64.

WRITE:/ lv_base64.

        结果验证

  • RSA加密示例-通过PSE证书文件加密

DATA: lv_output         TYPE xstring,
      lv_input_x        TYPE xstring,
      lv_input          TYPE string,
      lt_recipient_list TYPE STANDARD TABLE OF ssfinfo,
      ls_recipient_list LIKE LINE OF lt_recipient_list,
      lv_crc            TYPE ssfparms-ssfcrc.

DATA: lv_base64 TYPE string.

lv_input = '待加密字符串'.

lv_input_x = cl_bcs_convert=>string_to_xstring( lv_input ).

" 加密
ls_recipient_list-id = 'CN=user'." 一般为证书域名
APPEND ls_recipient_list TO lt_recipient_list.

CALL FUNCTION 'SSFW_KRN_ENVELOPE'
  EXPORTING
    str_format          = 'PKCS1-V1.5'
    str_pab             = '/tmp/user.pse'
    ostr_input_data     = lv_input_x
  IMPORTING
    ostr_enveloped_data = lv_output
  TABLES
    recipient_list      = lt_recipient_list
  EXCEPTIONS
    OTHERS              = 1.

CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
  EXPORTING
    input  = lv_output
  IMPORTING
    output = lv_base64.

WRITE:/ lv_base64.

        结果验证

  • RSA解密示例-通过PSE证书文件解密

DATA: lv_output         TYPE xstring,
      lv_input_x        TYPE xstring,
      lv_input          TYPE string,
      lt_recipient_list TYPE STANDARD TABLE OF ssfinfo,
      ls_recipient_list LIKE LINE OF lt_recipient_list,
      lv_crc            TYPE ssfparms-ssfcrc.

DATA: lv_base64 TYPE string.

" 解密
CLEAR lv_input_x.
CLEAR lt_recipient_list.
ls_recipient_list-id = 'CN=user'. " 一般为证书域名
ls_recipient_list-profile = '/tmp/user.pse'.
APPEND ls_recipient_list TO lt_recipient_list.
CALL FUNCTION 'SSFW_KRN_DEVELOPE'
  EXPORTING
    str_format                   = 'PKCS1-V1.5'
    ostr_enveloped_data          = lv_output
*   b_outdec                     = ''
  IMPORTING
    ostr_output_data             = lv_input_x
    crc                          = lv_crc
  TABLES
    recipient                    = lt_recipient_list
  EXCEPTIONS
    ssf_krn_error                = 1
    ssf_krn_noop                 = 2
    ssf_krn_nomemory             = 3
    ssf_krn_opinv                = 4
    ssf_krn_nossflib             = 5
    ssf_krn_recipient_error      = 6
    ssf_krn_input_data_error     = 7
    ssf_krn_invalid_par          = 8
    ssf_krn_invalid_parlen       = 9
    ssf_fb_input_parameter_error = 10
    OTHERS                       = 11.

lv_input = cl_bcs_convert=>xstring_to_string( iv_xstr =  lv_input_x iv_cp = '4110' ).

WRITE:/ lv_input.

        结果验证

  • RSA签名验签示例-使用证书签名验签

DATA: lv_output         TYPE xstring,
      lv_input_x        TYPE xstring,
      lv_chain_data     TYPE xstring,
      lv_input          TYPE string,
      lv_signer_name    TYPE string,
      lv_signed_data    TYPE xstring,
      lv_id             TYPE string,
      lv_profile        TYPE ssfparms-pab,
      lt_recipient_list TYPE STANDARD TABLE OF ssfinfo,
      ls_recipient_list LIKE LINE OF lt_recipient_list,
      lv_crc            TYPE ssfparms-ssfcrc.

DATA: lt_signer       TYPE STANDARD TABLE OF ssfinfo,
      ls_signer       TYPE ssfinfo,
      lt_certificates TYPE STANDARD TABLE OF ssfcertlin.

DATA: lv_format   TYPE ssfparms-ssfformat,
      lv_hashalg  TYPE ssfparms-ssfhashalg,
      lv_chainfmt TYPE ssfparms-ssfformat.

DATA:      lv_base64 TYPE string.

lv_input_x = '01020304'.
lv_profile = '/tmp/user.pse'.
lv_id      = 'CN=user'.

lv_format   = 'PKCS1-V1.5'.
lv_hashalg  = 'SHA256'.
lv_chainfmt = 'X509v3'.

" 签名
ls_signer-id      = lv_id. " 一般为证书域名
ls_signer-profile = lv_profile.
APPEND ls_signer TO lt_signer.

CALL FUNCTION 'SSFW_KRN_SIGN'
  EXPORTING
    str_format                   = lv_format
    str_hashalg                  = lv_hashalg
    str_chainfmt                 = lv_chainfmt
    ostr_input_data              = lv_input_x
  IMPORTING
    ostr_signed_data             = lv_signed_data
    str_signer_name              = lv_signer_name
    ostr_chain_data              = lv_chain_data
    crc                          = lv_crc
  TABLES
    signer                       = lt_signer
  EXCEPTIONS
    ssf_krn_error                = 1
    ssf_krn_noop                 = 2
    ssf_krn_nomemory             = 3
    ssf_krn_opinv                = 4
    ssf_krn_nossflib             = 5
    ssf_krn_input_data_error     = 6
    ssf_krn_invalid_par          = 7
    ssf_krn_invalid_parlen       = 8
    ssf_fb_input_parameter_error = 9
    OTHERS                       = 10.

" 验签
CLEAR lt_signer.
CALL FUNCTION 'SSFW_KRN_VERIFY'
  EXPORTING
    str_format                   = lv_format
    b_inc_certs                  = ''
    b_inenc                      = ''
    b_outdec                     = ''
    str_pab                      = lv_profile
    ostr_signed_data             = lv_signed_data
    ostr_input_data              = lv_input_x
    str_hashalg                  = lv_hashalg
    str_chainfmt                 = lv_chainfmt
    ostr_chain_data              = lv_chain_data
    str_signer_name              = lv_signer_name
  IMPORTING
    ostr_output_data             = lv_output
    crc                          = lv_crc
  TABLES
    signer_result_list           = lt_signer
    certificatelist              = lt_certificates
  EXCEPTIONS
    ssf_krn_error                = 1
    ssf_krn_noop                 = 2
    ssf_krn_nomemory             = 3
    ssf_krn_opinv                = 4
    ssf_krn_nossflib             = 5
    ssf_krn_input_data_error     = 6
    ssf_krn_invalid_par          = 7
    ssf_krn_invalid_parlen       = 8
    ssf_fb_input_parameter_error = 9
    OTHERS                       = 10.
  • 密钥

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0QgZrYkLPNredTBg9QtD z780aBQNW1ACwF84Sz/Q7aBiaiqSwLmSez6zhdZK4g7LRWkbb4VvadoVglnbzqDh JI0qeEh/YEUWp0mhYMw2c00wKB0ZWEZAevi+h9i8OhzAAnKB30eDqDIvfhSCkqmp TII/fqNwq0H5vXfwbiPAHEgdKHQtirZZx9fhaEN9/gfKc+sprjEMeZla/PphbkEW JnoN44uECrHghR72BLXrAZtkEk86ZfUSh1JuPjamKvX9qJiyTxxNPyC9+wjBn4+R J0yUvpcIrJ5jmdeogvorZe5DsdjoVNAA4u7c/YWpaq33O8491MyENoJUqMZde9AO 
RwIDAQAB 
-----END PUBLIC KEY-----
-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRCBmtiQs82t51 MGD1C0PPvzRoFA1bUALAXzhLP9DtoGJqKpLAuZJ7PrOF1kriDstFaRtvhW9p2hWC WdvOoOEkjSp4SH9gRRanSaFgzDZzTTAoHRlYRkB6+L6H2Lw6HMACcoHfR4OoMi9+ FIKSqalMgj9+o3CrQfm9d/BuI8AcSB0odC2KtlnH1+FoQ33+B8pz6ymuMQx5mVr8 +mFuQRYmeg3ji4QKseCFHvYEtesBm2QSTzpl9RKHUm4+NqYq9f2omLJPHE0/IL37 CMGfj5EnTJS+lwisnmOZ16iC+itl7kOx2OhU0ADi7tz9halqrfc7zj3UzIQ2glSo xl170A5HAgMBAAECggEAMphqVrXAMZesluMB5O44GLXoQnTwErUYJWYm4xfsQ0g5 6gaqBNomGYzAuVl4QKViEEfzqxe6Mv3ljOqhKK+KL2W37OtnYW73n8BTvnFPkLMT P/JjKxm+C8XfoFQWo15IH4+F3fyaYoDbPAJM5KEKaIlyQv3ejKVohLLeUFp46p8d Xua2SdodXkfEP6SkQXzCurg9JPXL1HKOXbtduskDtjHgYaK/2r5e4RkqPpM9rJQN mP57d0WwAPAbOdFoQ4E/lh+5SWW489IFrGyiQmUgmoAF+eFbZUXYZPAp0f5dZERj 25vwHIaTQc9t0qBkPTog/Tqr6eQZGn8nnPxOGHH64QKBgQD/Y/HGjMpRShD8KjOi bULN+HMTwSmm/aE06hTsBNqiQJSONDye2mhhdknziZa4yvYOkaR41YCX5K5vkNB3 hHZRUzzfbDXax3VFIlcw7obzCJV+xI/R6WCggLqQfS3Uw7PAzdTVYY4oxDRvhBfY jStHvcsnROfZdNZtr10pYRiBMQKBgQDRh9QXOlY8KM6mP5zsVLw0HncaeUEoiuQT adZIAzek25+DqaQ+AVZllZXOmdMyigUkv5aoGijeARA3ADXIUdA7x5ytL4ILvTnN iE3qwh4lYU6uJSkAuMvEcOmZzaqm3NBNy8u5V/LJaXP9ifu4mX+NHLRMmYsuTi63 ce6mG8fo9wKBgQDBpenk8EpUOwIIAoPmbEyUWwf++Z94pKZAtiGpGMEi+C7saMVy eg9dn1DRngkwE41hXKPGj7US924g4ECB72m7no7wpl9rhYPxKOnOC3899stMNQUM WJZQ/Wr5NkGzK7U3w5rXNUKSvLs5t4JRTDF+E3ZgT0oxw/r3bloIjzwCcQKBgQCS Hy+Bo2VQPwUeW26MQeueTUCyba1LINE92KlfPx8nESKFJ2Eq/LPL1C3NDumCbU54 +kOOp++oIwWz1amsMaIOjn5tKJyAo04UT+JGvWlYmCvOtouJvVYdgMDoSc2g4I1E M8O3VeYzIB+LyRaK/kE9n679XHb7q/pYZFQR833OsQKBgCWnWtuNt4QPelesOVbh 2Oqoz0JVjMM7GWFELpVsdI4hXpcFDPnWjK1hUMI8KeUYXzYF85D1fJCtniK2G9jF QfuVRUh2CkzHuQ7X28pqwqBqLI3uj4WmKjq08PV32G9TPQSzp371f9vd9CGCJ6s2 
ysUQJ190VIhkRlQuU0j/1Pnj 
-----END PRIVATE KEY-----

        测试用pse文件:ABAPRSA加密实现(加解密及签名)-测试用pse证书文件-Java文档类资源-CSDN下载ABAPRSA加密实现(加解密及签名)-测试用pse证书文件使用对应私钥生成ID位CN=us更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/xiefireworks/85476825

  • 参考

        函数组单元测试类 lcl_ssfw_test

       可将如下代码拷贝至程序中调试

classslcl_ssfw_test.txt-Java文档类资源-CSDN下载classslcl_ssfw_test.txt更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/xiefireworks/85393784        pse文件生成

        使用openssl根据rsa key生成pfx证书文件

openssl req -x509 -sha256 -key rsa.key -out user1.cer -days 3650 -subj '/CN=user'
openssl pkcs12 -export -inkey rsa.key -in user1.cer -out user.pfx -nodes

        在sap中通过如下命令生成sap pse文件https://help.sap.com/doc/saphelp_nw74/7.4.16/en-US/49/458f193a293b5be10000000a42189b/content.htm?no_cache=truehttps://help.sap.com/doc/saphelp_nw74/7.4.16/en-US/49/458f193a293b5be10000000a42189b/content.htm?no_cache=true

sapgenpse import_p12 -x "" -p user.pse user.pfx
  • 注意事项

        1. 实际使用的是base64处理后的加密或签名后的xstring字符串

        2. pse文件的生成可以通过私钥key生成,RSA加密中根据私钥中包含的数据可得到公钥

        3. 加解密时根据要求正确使用参数str_format ,str_sym_encr_alg确定版本和算法;加密时ID和pse文件路径通过参数lt_recipient_list和str_pab传递,解密时通过参数lt_recipient_list传递。

        4. 签名时根据要求正确使用参数str_format  ,str_chainfmt,str_hashalg 来确定签名算法等;签名时ID和pse文件路径通过参数lt_signer传递,验签时通过参数str_pab和str_signer_name传递。

        5. SSFW函数组中函数调用system function SSF_ABAP_SERVICE 的日志可通过SM21查看

二、openssl命令行实现

  • 示例代码

DATA: lv_output TYPE xstring,
      lv_input  TYPE string.

DATA: lv_base64      TYPE string,
      lv_pubbase64   TYPE string,
      lv_pubfieltext TYPE string.

DATA: lv_inputfile  TYPE string,
      lv_pubkeyfile TYPE string,
      lv_outputfile TYPE string.

DATA:lv_parameters 		TYPE sxpgcolist-parameters,
     lv_status     		TYPE extcmdexex-status,
     lv_exitcode   		TYPE extcmdexex-exitcode,
     lt_exec_protocol	TYPE TABLE OF btcxpm.

DATA: timestamp TYPE timestampl,
      str       TYPE string.

GET TIME STAMP FIELD timestamp.
str = timestamp.
REPLACE ALL OCCURRENCES OF '.' IN str WITH ''.
CONDENSE str NO-GAPS.
lv_inputfile  = '/tmp/temp_input'   && str && '.txt'.
lv_pubkeyfile = '/tmp/temp_pubkey'  && str && '.pem'.
lv_outputfile = '/tmp/temp_output'  && str && '.txt'.

lv_input = '待加密字符串'.

" 加密
lv_pubbase64 = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0QgZrYkLPNredTBg9QtD'
            && 'z780aBQNW1ACwF84Sz/Q7aBiaiqSwLmSez6zhdZK4g7LRWkbb4VvadoVglnbzqDh'
            && 'JI0qeEh/YEUWp0mhYMw2c00wKB0ZWEZAevi+h9i8OhzAAnKB30eDqDIvfhSCkqmp'
            && 'TII/fqNwq0H5vXfwbiPAHEgdKHQtirZZx9fhaEN9/gfKc+sprjEMeZla/PphbkEW'
            && 'JnoN44uECrHghR72BLXrAZtkEk86ZfUSh1JuPjamKvX9qJiyTxxNPyC9+wjBn4+R'
            && 'J0yUvpcIrJ5jmdeogvorZe5DsdjoVNAA4u7c/YWpaq33O8491MyENoJUqMZde9AO'
            && 'RwIDAQAB'.

lv_pubfieltext = '-----BEGIN PUBLIC KEY-----' && cl_abap_char_utilities=>cr_lf+1(1) && lv_pubbase64
                 && cl_abap_char_utilities=>cr_lf+1(1)     && '-----END PUBLIC KEY-----' .

" 写入密钥及明文
OPEN DATASET lv_inputfile FOR OUTPUT IN BINARY MODE.
TRANSFER lv_input TO lv_inputfile.
CLOSE DATASET lv_inputfile.

OPEN DATASET lv_pubkeyfile FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
TRANSFER lv_pubfieltext TO lv_pubkeyfile.
CLOSE DATASET lv_pubkeyfile.

lv_parameters = |rsautl -encrypt -in { lv_inputfile } -inkey { lv_pubkeyfile } -pubin -out { lv_outputfile }|.

CALL FUNCTION 'SXPG_COMMAND_EXECUTE'
  EXPORTING
    commandname                   = 'ZOPENSSL'
    additional_parameters         = lv_parameters
    operatingsystem               = sy-opsys
  IMPORTING
    status                        = lv_status
    exitcode                      = lv_exitcode
  TABLES
    exec_protocol                 = lt_exec_protocol
  EXCEPTIONS
    no_permission                 = 1
    command_not_found             = 2
    parameters_too_long           = 3
    security_risk                 = 4
    wrong_check_call_interface    = 5
    program_start_error           = 6
    program_termination_error     = 7
    x_error                       = 8
    parameter_expected            = 9
    too_many_parameters           = 10
    illegal_command               = 11
    wrong_asynchronous_parameters = 12
    cant_enq_tbtco_entry          = 13
    jobcount_generation_error     = 14
    OTHERS                        = 15.

" 读取加密后文件
IF sy-subrc = 0 AND lv_status <> 'E'.
  OPEN DATASET lv_outputfile FOR INPUT IN BINARY MODE.
  READ DATASET lv_outputfile INTO lv_output.
  CLOSE DATASET lv_outputfile.
ENDIF.

" 删除临时文件
 DELETE DATASET lv_inputfile  .
 DELETE DATASET lv_pubkeyfile .
 DELETE DATASET lv_outputfile .

CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
  EXPORTING
    input  = lv_output
  IMPORTING
    output = lv_base64.

WRITE: / lv_base64.
  • SM69配置

  • 参考

        openssl命令 openssl 非对称加密算法RSA命令详解 - 走看看

三、开源代码实现

        可参考博客RSA Encryption in ABAP | SAP Blogs

        大数计算开源类代码
Z04_BIGINTX.txt-Java文档类资源-CSDN下载Z04_BIGINTX.txt更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/xiefireworks/85393797

2022.6.8

        更新pse文件及签名验签示例代码 

Fireworks https://mp.csdn.net/mp_blog/creation/editor/124809161 

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值