ABAP RSA方式调用银行API

打印 上一主题 下一主题

主题 536|帖子 536|积分 1608

一、RSA简介

RSA是非对称加密的一种。
对称加密算法在加密和解密时使用的是同一个秘钥;
非对称加密算法需要一对密钥来加密解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。一个加密,一个解密,由双方各保留一个进行操作。这样,在不传输秘钥的情况下,双方可以针对信息进行加解密,避免了直接传输秘钥可能导致的安全问题。
二、RSA加解密与签名验签

一般来说,有两种场景:加密解密和签名验签
加密解密:使用公钥加密,私钥解密
签名验签:使用私钥加密(签名),公钥解密(验签)
例如:B生成一对密钥,向A提供公钥,B保留私钥
加密:防止信息泄露
当A系统传输数据给B系统,担心报文明文传输会导致信息泄露,则可使用公钥对报文进行加密,以防传输过程中信息泄露。B接收加密报文,通过私钥进行解密
签名:防止信息篡改
当B接收后返回消息给A,担心返回消息被修改,A接收到错误消息,则可使用秘钥进行签名,并将签名和返回报文一起发送给A。A通过公钥进行验签,发现签名解析后和返回报文数据一致,证明报文没有被中间拦截篡改
三、代码实现

1、证书加密解密与签名验签

使用秘钥生成PSE证书方式进行加密解密与签名验签
生成一对密钥后,将私钥文件RSA.key上传到SAP服务器,前后需要加标注,否则不能正常使用

通过命令生成PSE文件,此操作需要BASIS协助
  1. /tmp/rsa > openssl req -x509 -sha256 -key rsa.key -out user1.cer -days 3650 -subj '/CN=user1'
  2. /tmp/rsa > openssl pkcs12 -export -inkey rsa.key -in user1.cer -out user1.pfx -nodes
  3. Enter Export Password:
  4. Verifying - Enter Export Password:
  5. /tmp/rsa > setenv SECUDIR $PWD
  6. /tmp/rsa > sapgenpse import_p12 -x "" -p user1.pse user1.pfx
  7. Found key 'INDEX=0,SIG=YES,ENC=YES,MD5-FINGERPRINT=3B9E 77DD E5E4 3371 19FA 2FCF D1CA 512F,KEYID=3D1E2BC7E33500A3D2A098B63FE9962A6B63318C'
  8. !!! WARNING: For security reasons it is recommended to use a PIN/passphrase
  9. !!! WARNING: which is at least 8 characters long and contains characters in
  10. !!! WARNING: upper and lower case, numbers and non-alphanumeric symbols.
  11. PSE "/tmp/rsa/user1.pse" was written
复制代码
证书加密解密代码:
  1. DATA: lv_output         TYPE xstring,
  2.       lv_input_x        TYPE xstring,
  3.       lv_input          TYPE string,
  4.       lt_recipient_list TYPE STANDARD TABLE OF ssfinfo,
  5.       ls_recipient_list LIKE LINE OF lt_recipient_list,
  6.       lv_crc            TYPE ssfparms-ssfcrc.
  7. DATA: lf_output        TYPE xstring.
  8. DATA: lf_plain_input_x TYPE xstring.
  9. DATA: lf_plain_input   TYPE string.
  10. DATA: msg_file_name    TYPE string.
  11. DATA: it_recipient_list TYPE STANDARD TABLE OF ssfinfo,
  12.       wa_recipient_list LIKE LINE OF it_recipient_list.
  13. "原文
  14. lf_plain_input = '一段需要处理的报文'.
  15. "转为xstring
  16. CALLFUNCTION'SCMS_STRING_TO_XSTRING'
  17.   EXPORTING
  18.     text =lf_plain_input
  19.   IMPORTING
  20.     buffer =lf_plain_input_x.
  21. "证书域名
  22. wa_recipient_list-id ='CN=user1'.
  23. APPENDwa_recipient_listTOit_recipient_list.
  24. "加密函数
  25. CALLFUNCTION'SSFW_KRN_ENVELOPE'
  26.   EXPORTING
  27.     str_format ='PKCS1-V1.5'
  28.     str_pab ='/tmp/rsa/user1.pse'"服务器中证书路径
  29.     ostr_input_data =lf_plain_input_x
  30.   IMPORTING
  31.     ostr_enveloped_data =lf_output
  32.   TABLES
  33.     recipient_list =it_recipient_list
  34.   EXCEPTIONS
  35.     OTHERS =1.
  36. "展示加密后信息
  37. PERFORMshow_dataUSINGlf_output.
  38. SKIP.
  39. CLEARlv_input_x.
  40. CLEARlt_recipient_list.
  41. ls_recipient_list-id ='CN=user1'."一般为证书域名
  42. ls_recipient_list-profile ='/tmp/rsa/user1.pse'.
  43. APPENDls_recipient_listTOlt_recipient_list.
  44. "解密
  45. CALLFUNCTION'SSFW_KRN_DEVELOPE'
  46.   EXPORTING
  47.     str_format ='PKCS1-V1.5'
  48.     ostr_enveloped_data =lf_output
  49. *b_outdec =''
  50.   IMPORTING
  51.     ostr_output_data =lv_input_x
  52.     crc =lv_crc
  53.   TABLES
  54.     recipient =lt_recipient_list
  55.   EXCEPTIONS
  56.     ssf_krn_error =1
  57.     ssf_krn_noop =2
  58.     ssf_krn_nomemory =3
  59.     ssf_krn_opinv =4
  60.     ssf_krn_nossflib =5
  61.     ssf_krn_recipient_error =6
  62.     ssf_krn_input_data_error =7
  63.     ssf_krn_invalid_par =8
  64.     ssf_krn_invalid_parlen =9
  65.     ssf_fb_input_parameter_error =10
  66.     OTHERS =11.
  67. "根据UTF-8格式转为string类型数据
  68. lv_input =cl_bcs_convert=>xstring_to_string(iv_xstr =lv_input_xiv_cp ='4110').
  69. WRITE:/lv_input.
  70. FORM show_data USING data_x TYPE xstring.
  71.   DATA:data_lenTYPEi,
  72.         i1TYPEiVALUE0,
  73.         i2TYPEiVALUE32.
  74.   data_len =xstrlen(data_x).
  75.   WHILE(i1<data_len).
  76.     i2 =nmin(val1 =i2
  77.                val2 =data_len).
  78.     WRITE:/data_x+i1(i2).
  79.     i1 =i1+32.
  80.   ENDWHILE.
  81. ENDFORM.
复制代码
四、简述调用API过程

使用HTTP方式调用银行API
  1. DATA: lv_output         TYPE xstring,
  2.       lv_input_x        TYPE xstring,
  3.       lv_input          TYPE string,
  4.       lt_recipient_list TYPE STANDARD TABLE OF ssfinfo,
  5.       ls_recipient_list LIKE LINE OF lt_recipient_list,
  6.       lv_crc            TYPE ssfparms-ssfcrc.
  7. DATA: lf_input_data    TYPE xstring,
  8.           lf_signed_data   TYPE xstring,
  9.           ls_signer        TYPE ssfinfo,          "ssfinfoext is tested by CL_SMIME
  10.           lt_signer        TYPE TABLE OF ssfinfo, "ssfinfoext is tested by CL_SMIME
  11.           lf_crc           TYPE ssfreturn,
  12.           lf_signer_name   TYPE string,
  13.           lf_chain_dataTYPExstring,
  14.           lf_output_dataTYPExstring,
  15.           lf_inputv_dataTYPExstring,
  16.           ls_certificateTYPEssfcertlin,
  17.           lt_certificatesTYPETABLEOFssfcertlin,
  18.           lf_subject(256)TYPEc.
  19. "原文
  20. lv_input ='一段需要处理的报文'.
  21. CALLFUNCTION'SCMS_STRING_TO_XSTRING'
  22.   EXPORTING
  23.     text =lv_input
  24.   IMPORTING
  25.     buffer =lv_input_x.
  26. "签名
  27. ls_signer-id ='CN=user1'."一般为证书域名
  28. ls_signer-profile ='/tmp/rsa/user1.pse'.
  29. APPENDls_signerTOlt_signer.
  30. CALLFUNCTION'SSFW_KRN_SIGN'
  31.       EXPORTING
  32.         ssftoolkit ='SAPSECULIB'
  33.         str_format ='PKCS1-V1.5'
  34.         b_inc_certs =''
  35.         b_detached ='X'
  36.         b_inenc =''
  37.         str_hashalg ='SHA256'"'SHA1'
  38.         str_chainfmt =''
  39.         ostr_input_data =lv_input_x
  40.       IMPORTING
  41.         ostr_signed_data =lf_signed_data
  42.         str_signer_name =lf_signer_name
  43. *ostr_signer_keyid =
  44.         ostr_chain_data =lf_chain_data
  45.         crc =lf_crc
  46.       TABLES
  47.         signer =lt_signer
  48.       EXCEPTIONS
  49.         ssf_krn_error =1
  50.         ssf_krn_noop =2
  51.         ssf_krn_nomemory =3
  52.         ssf_krn_opinv =4
  53.         ssf_krn_nossflib =5
  54.         ssf_krn_signer_list_error =6
  55.         ssf_krn_input_data_error =7
  56.         ssf_krn_invalid_par =8
  57.         ssf_krn_invalid_parlen =9
  58.         ssf_fb_input_parameter_error =10
  59.         OTHERS =11.
  60. PERFORMshow_dataUSINGlf_signed_data.
  61. SKIP.
  62. lf_inputv_data =lv_input_x.
  63. "验签
  64. CLEARlt_signer.
  65. *verifysignature
  66.     CALLFUNCTION'SSFW_KRN_VERIFY'
  67.       EXPORTING
  68.         ssftoolkit ='SAPSECULIB'
  69.         str_format ='PKCS1-V1.5'
  70.         b_inc_certs =''
  71.         b_inenc =''
  72.         b_outdec =''
  73.         str_pab ='/tmp/rsa/user1.pse'
  74. *str_pab_password =
  75.         ostr_signed_data =lf_signed_data
  76.         ostr_input_data =lf_inputv_data
  77.         str_hashalg ='SHA256'"'SHA1'
  78.         str_chainfmt =''
  79. *ostr_chain_data =''
  80.         str_signer_name =lf_signer_name
  81. *ostr_signer_keyid =
  82.         crl_profile =''
  83.       IMPORTING
  84.         ostr_output_data =lf_output_data
  85.         crc =lf_crc
  86.       TABLES
  87.         signer_result_list =lt_signer
  88.         certificatelist =lt_certificates
  89.       EXCEPTIONS
  90.         ssf_krn_error =1
  91.         ssf_krn_noop =2
  92.         ssf_krn_nomemory =3
  93.         ssf_krn_opinv =4
  94.         ssf_krn_nossflib =5
  95.         ssf_krn_input_data_error =6
  96.         ssf_krn_invalid_par =7
  97.         ssf_krn_invalid_parlen =8
  98.         ssf_fb_input_parameter_error =9
  99.         OTHERS =10.
  100. IFsy-subrc<>0.
  101. *Implementsuitableerrorhandlinghere
  102.   WRITE:/sy-subrc.
  103. ENDIF.
  104. lv_input =cl_bcs_convert=>xstring_to_string(iv_xstr =lf_output_dataiv_cp ='4110').
  105. WRITE:/lv_input.
  106. FORM show_data USING data_x TYPE xstring.
  107.   DATA:data_lenTYPEi
  108.       ,i1TYPEiVALUE0
  109.       ,i2TYPEiVALUE32.
  110.   data_len =xstrlen(data_x).
  111.   WHILE(i1<data_len).
  112.     i2 =nmin(val1 =i2
  113.                val2 =data_len).
  114.     WRITE:/data_x+i1(i2).
  115.     i1 =i1+32.
  116.   ENDWHILE.
  117. ENDFORM.
复制代码
根据上述签名之后,得到签名字符串拼接到发送报文中

 发送数据并获得返回消息即可
  1. DATA:lv_input_x        TYPE xstring,
  2.       lv_data TYPE string,
  3.       lv_xdata TYPE xstring,
  4.       lv_input          TYPE string,
  5.       lf_signed_data   TYPE xstring,
  6.       lf_signer_name   TYPE string,
  7.       lf_chain_data    TYPE xstring,
  8.       lf_output_data   TYPE xstring,
  9.       ls_signer        TYPE ssfinfo,          "ssfinfoext is tested by CL_SMIME
  10.       lt_signer        TYPE TABLE OF ssfinfo, "ssfinfoext is tested by CL_SMIME
  11.       lt_certificates  TYPE TABLE OF ssfcertlin,
  12.       lf_crc           TYPE ssfreturn.
  13. DATA: lv_base64    TYPE string,
  14.       lv_pubkey    TYPE xstring,
  15.       lv_pubbase64 TYPE string,
  16.       lv_str       TYPE string.
  17. <br>"签名模板
  18. lv_data = 'json字符串签名模板'.
  19. lv_xdata = cl_abap_codepage=>convert_to( source   = lv_data
  20.                                          codepage = 'UTF-8' ).
  21.   "签名
  22.   lv_input = 'g0r+iYM0FYAHworrKa+XzL/4FO/ci+S0HZr1pJFAf1/Dtkr+pnpFUWM'
  23.           && 'zf3oHBeJDL3rcCgCqzUOYhpss3MKtOAR/rttdu8a5FQ1G456uYF7D5r'.
  24. CALL FUNCTION 'SCMS_BASE64_DECODE_STR'
  25.   EXPORTING
  26.     input  = lv_input
  27. *   UNESCAPE       = 'X'
  28.   IMPORTING
  29.     output = lv_input_x
  30.   EXCEPTIONS
  31.     failed = 1
  32.     OTHERS = 2.
  33.   "公钥
  34.   lv_pubbase64 = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwFgHD4kzEVPdOj0'
  35.               && 'YCX+zp5r6R52MY0O7BsTCLT7aHaxsANsvI9ABGx3OaTVlPB59M6GPb'.
  36. CALL FUNCTION 'SCMS_BASE64_DECODE_STR'
  37.   EXPORTING
  38.     input  = lv_pubbase64
  39. *   UNESCAPE       = 'X'
  40.   IMPORTING
  41.     output = lv_pubkey
  42.   EXCEPTIONS
  43.     failed = 1
  44.     OTHERS = 2.
  45. " 模数
  46. lv_str = lv_pubkey.
  47. DATA(length) = strlen( lv_str ).
  48. IF length > 514." 2048位密钥
  49.   DATA(pos) = length - 10 - 514.
  50.   lv_str = lv_str+pos(514).
  51. ELSEIF length > 256." 1024位密钥
  52.   pos = length - 10 - 256.
  53.   lv_str = lv_str+pos(256).
  54. ENDIF.
  55. " 函数使用密钥格式
  56. lv_str = 'R:m=' && lv_str && ':e=010001:'.
  57. lv_pubkey = cl_bcs_convert=>string_to_xstring( lv_str ).
  58.   CALL FUNCTION 'SSFW_KRN_VERIFY'
  59.       EXPORTING
  60.         ssftoolkit                   = 'SAPSECULIB'
  61.         str_format                   = 'PKCS1-V1.5'
  62.         b_inc_certs                  = ''
  63.         b_inenc                      = ''
  64.         b_outdec                     = ''
  65.         str_pab                      = '<no_certificate_check>'
  66. *       str_pab_password             =
  67.         ostr_signed_data             = lv_input_x
  68.         ostr_input_data              = lv_xdata
  69.         str_hashalg                  = 'SHA1'
  70.         str_chainfmt                 = 'KEYVALUE'
  71.         ostr_chain_data              = lv_pubkey
  72. *       ostr_signer_keyid            =
  73.         crl_profile                  = ''
  74.       IMPORTING
  75.         ostr_output_data             = lf_output_data
  76.         crc                          = lf_crc
  77.       TABLES
  78.         signer_result_list           = lt_signer
  79.         certificatelist              = lt_certificates
  80.       EXCEPTIONS
  81.         ssf_krn_error                = 1
  82.         ssf_krn_noop                 = 2
  83.         ssf_krn_nomemory             = 3
  84.         ssf_krn_opinv                = 4
  85.         ssf_krn_nossflib             = 5
  86.         ssf_krn_input_data_error     = 6
  87.         ssf_krn_invalid_par          = 7
  88.         ssf_krn_invalid_parlen       = 8
  89.         ssf_fb_input_parameter_error = 9
  90.         OTHERS                       = 10.
  91. IF sy-subrc <> 0.
  92. * Implement suitable error handling here
  93.   WRITE:/ sy-subrc.
  94. ENDIF.
  95. WRITE:/ lf_crc.
  96. lv_input = cl_bcs_convert=>xstring_to_string( iv_xstr =  lf_output_data iv_cp = '4110' ).
  97. WRITE:/ lv_input.
复制代码
调用时报错
  1. "创建HTTP对象
  2. CALL METHOD cl_http_client=>create_by_url
  3.     EXPORTING
  4.       url    = ls_ghinfo-zurl
  5.     IMPORTING
  6.       client = lo_http_client.
  7. lo_http_client->propertytype_redirect = lo_http_client->co_disabled .
  8.   CALL METHOD lo_http_client->request->set_header_field
  9.     EXPORTING
  10.       name  = '~request_method'
  11.       value = 'POST'.                 "
  12.   CALL METHOD lo_http_client->request->set_header_field
  13.     EXPORTING
  14.       name  = '~request_protocol'
  15.       value = 'HTTP/1.1'.
  16.   CALL METHOD lo_http_client->request->set_header_field
  17.     EXPORTING
  18.       name  = 'Content-Type'
  19.       value = 'application/x-www-form-urlencoded; charset=UTF-8'.
复制代码
 这是因为调用HTTPS地址,没有将网页证书导入到SAP系统。可以在浏览器中下载对应地址的证书,导入SAP系统即可

五、致谢

这是一篇站在前人肩膀上完成的博客,各位前辈的资料,给予了本人极大的帮助,尤其感谢CSDN博主​​Fireworks_me​​对我疑惑的耐心解答,非常感谢!
参考文档:
​https://blogs.sap.com/2021/04/13/rsa-encryption-in-abap/ ​
​https://blog.csdn.net/xiefireworks/article/details/124809161?spm=1001.2014.3001.5501 ​
​https://blog.csdn.net/somehow1002/article/details/117092352 ​​​
​​https://blog.51cto.com/wushank/1915795​​
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

盛世宏图

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表