一、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協助
/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
證書加密解密代碼:
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: lf_output TYPE xstring. DATA: lf_plain_input_x TYPE xstring. DATA: lf_plain_input TYPE string. DATA: msg_file_name TYPE string. DATA: it_recipient_list TYPE STANDARD TABLE OF ssfinfo, wa_recipient_list LIKE LINE OF it_recipient_list. "原文 lf_plain_input = '一段需要處理的報文'. "轉為xstring CALLFUNCTION'SCMS_STRING_TO_XSTRING' EXPORTING text =lf_plain_input IMPORTING buffer =lf_plain_input_x. "證書域名 wa_recipient_list-id ='CN=user1'. APPENDwa_recipient_listTOit_recipient_list. "加密函式 CALLFUNCTION'SSFW_KRN_ENVELOPE' EXPORTING str_format ='PKCS1-V1.5' str_pab ='/tmp/rsa/user1.pse'"服務器中證書路徑 ostr_input_data =https://www.cnblogs.com/BinGeneral/p/lf_plain_input_x IMPORTING ostr_enveloped_data =lf_output TABLES recipient_list =it_recipient_list EXCEPTIONS OTHERS =1. "展示加密后資訊 PERFORMshow_dataUSINGlf_output. SKIP. CLEARlv_input_x. CLEARlt_recipient_list. ls_recipient_list-id ='CN=user1'."一般為證書域名 ls_recipient_list-profile ='/tmp/rsa/user1.pse'. APPENDls_recipient_listTOlt_recipient_list. "解密 CALLFUNCTION'SSFW_KRN_DEVELOPE' EXPORTING str_format ='PKCS1-V1.5' ostr_enveloped_data =lf_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. "根據UTF-8格式轉為string型別資料 lv_input =cl_bcs_convert=>xstring_to_string(iv_xstr =lv_input_xiv_cp ='4110'). WRITE:/lv_input. FORM show_data USING data_x TYPE xstring. DATA:data_lenTYPEi, i1TYPEiVALUE0, i2TYPEiVALUE32. 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.
證書簽名驗簽代碼:
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: lf_input_data TYPE xstring, lf_signed_data TYPE xstring, ls_signer TYPE ssfinfo, "ssfinfoext is tested by CL_SMIME lt_signer TYPE TABLE OF ssfinfo, "ssfinfoext is tested by CL_SMIME lf_crc TYPE ssfreturn, lf_signer_name TYPE string, lf_chain_dataTYPExstring, lf_output_dataTYPExstring, lf_inputv_dataTYPExstring, ls_certificateTYPEssfcertlin, lt_certificatesTYPETABLEOFssfcertlin, lf_subject(256)TYPEc. "原文 lv_input ='一段需要處理的報文'. CALLFUNCTION'SCMS_STRING_TO_XSTRING' EXPORTING text =lv_input IMPORTING buffer =lv_input_x. "簽名 ls_signer-id ='CN=user1'."一般為證書域名 ls_signer-profile ='/tmp/rsa/user1.pse'. APPENDls_signerTOlt_signer. CALLFUNCTION'SSFW_KRN_SIGN' EXPORTING ssftoolkit ='SAPSECULIB' str_format ='PKCS1-V1.5' b_inc_certs ='' b_detached ='X' b_inenc ='' str_hashalg ='SHA256'"'SHA1' str_chainfmt ='' ostr_input_data =lv_input_x IMPORTING ostr_signed_data =lf_signed_data str_signer_name =lf_signer_name *ostr_signer_keyid = ostr_chain_data =https://www.cnblogs.com/BinGeneral/p/lf_chain_data crc =lf_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_signer_list_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. PERFORMshow_dataUSINGlf_signed_data. SKIP. lf_inputv_data =lv_input_x. "驗簽 CLEARlt_signer. *verifysignature CALLFUNCTION'SSFW_KRN_VERIFY' EXPORTING ssftoolkit ='SAPSECULIB' str_format ='PKCS1-V1.5' b_inc_certs ='' b_inenc ='' b_outdec ='' str_pab ='/tmp/rsa/user1.pse' *str_pab_password = ostr_signed_data =https://www.cnblogs.com/BinGeneral/p/lf_signed_data ostr_input_data =lf_inputv_data str_hashalg ='SHA256'"'SHA1' str_chainfmt ='' *ostr_chain_data ='' str_signer_name =lf_signer_name *ostr_signer_keyid = crl_profile ='' IMPORTING ostr_output_data =lf_output_data crc =lf_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. IFsy-subrc<>0. *Implementsuitableerrorhandlinghere WRITE:/sy-subrc. ENDIF. lv_input =cl_bcs_convert=>xstring_to_string(iv_xstr =lf_output_dataiv_cp ='4110'). WRITE:/lv_input. FORM show_data USING data_x TYPE xstring. DATA:data_lenTYPEi ,i1TYPEiVALUE0 ,i2TYPEiVALUE32. 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.
2、公鑰驗簽
當對方系統收到資料回傳時,需要對回傳的簽名使用對方系統提供的公鑰進行驗簽,證明對方回傳的資料沒有被篡改
DATA:lv_input_x TYPE xstring, lv_data TYPE string, lv_xdata TYPE xstring, lv_input TYPE string, lf_signed_data TYPE xstring, lf_signer_name TYPE string, lf_chain_data TYPE xstring, lf_output_data TYPE xstring, ls_signer TYPE ssfinfo, "ssfinfoext is tested by CL_SMIME lt_signer TYPE TABLE OF ssfinfo, "ssfinfoext is tested by CL_SMIME lt_certificates TYPE TABLE OF ssfcertlin, lf_crc TYPE ssfreturn. DATA: lv_base64 TYPE string, lv_pubkey TYPE xstring, lv_pubbase64 TYPE string, lv_str TYPE string.
"簽名模板 lv_data = 'json字串簽名模板'. lv_xdata = cl_abap_codepage=>convert_to( source = lv_data codepage = 'UTF-8' ). "簽名 lv_input = 'g0r+iYM0FYAHworrKa+XzL/4FO/ci+S0HZr1pJFAf1/Dtkr+pnpFUWM' && 'zf3oHBeJDL3rcCgCqzUOYhpss3MKtOAR/rttdu8a5FQ1G456uYF7D5r'. CALL FUNCTION 'SCMS_BASE64_DECODE_STR' EXPORTING input = lv_input * UNESCAPE = 'X' IMPORTING output = lv_input_x EXCEPTIONS failed = 1 OTHERS = 2. "公鑰 lv_pubbase64 = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwFgHD4kzEVPdOj0' && 'YCX+zp5r6R52MY0O7BsTCLT7aHaxsANsvI9ABGx3OaTVlPB59M6GPb'. 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 ). CALL FUNCTION 'SSFW_KRN_VERIFY' EXPORTING ssftoolkit = 'SAPSECULIB' str_format = 'PKCS1-V1.5' b_inc_certs = '' b_inenc = '' b_outdec = '' str_pab = '<no_certificate_check>' * str_pab_password = ostr_signed_data =https://www.cnblogs.com/BinGeneral/p/ lv_input_x ostr_input_data = lv_xdata str_hashalg = 'SHA1' str_chainfmt = 'KEYVALUE' ostr_chain_data = lv_pubkey * ostr_signer_keyid = crl_profile = '' IMPORTING ostr_output_data = lf_output_data crc = lf_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. IF sy-subrc <> 0. * Implement suitable error handling here WRITE:/ sy-subrc. ENDIF. WRITE:/ lf_crc. lv_input = cl_bcs_convert=>xstring_to_string( iv_xstr = lf_output_data iv_cp = '4110' ). WRITE:/ lv_input.
四、簡述呼叫API程序
使用HTTP方式呼叫銀行API
"創建HTTP物件 CALL METHOD cl_http_client=>create_by_url EXPORTING url = ls_ghinfo-zurl IMPORTING client = lo_http_client. lo_http_client->propertytype_redirect = lo_http_client->co_disabled . CALL METHOD lo_http_client->request->set_header_field EXPORTING name = '~request_method' value = 'POST'. " CALL METHOD lo_http_client->request->set_header_field EXPORTING name = '~request_protocol' value = 'HTTP/1.1'. CALL METHOD lo_http_client->request->set_header_field EXPORTING name = 'Content-Type' value = 'application/x-www-form-urlencoded; charset=UTF-8'.
根據上述簽名之后,得到簽名字串拼接到發送報文中

發送資料并獲得回傳訊息即可
lv_len = strlen( gv_json_send ). CALL METHOD lo_http_client->request->set_cdata EXPORTING data = gv_json_send offset = 0 length = lv_len. CALL METHOD lo_http_client->send EXCEPTIONS http_communication_failure = 1 http_invalid_state = 2. CALL METHOD lo_http_client->receive EXCEPTIONS http_communication_failure = 1 http_invalid_state = 2 http_processing_failed = 3. IF sy-subrc <> 0. DATA:l_sysubrc TYPE sysubrc, l_error_text TYPE string. l_sysubrc = sy-subrc. CALL METHOD lo_http_client->get_last_error IMPORTING code = l_sysubrc message = l_error_text. ENDIF. CALL METHOD lo_http_client->response->get_status IMPORTING code = http_status_code reason = status_text. e_message = '呼叫狀態:' && http_status_code && ',狀態文本:' && status_text. CALL METHOD lo_http_client->response->get_cdata RECEIVING data = w_result .
呼叫時報錯
SSL handshake with xxx.com.cn:443 failed: SSSLERR_PEER_CERT_UNTRUSTED (-102) The peer's X.509 Certificate (chain) is untrusted SapSSLSessionStartNB()==SSSLERR_PEER_CERT_UNTRUSTED
這是因為呼叫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???
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/498817.html
標籤:SAP
