11

ABAP RSA方式调用银行API

 1 year ago
source link: https://blog.51cto.com/BinGeneral/5378941
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、RSA简介

RSA是非对称加密的一种。

对称加密算法在加密和解密时使用的是同一个秘钥;

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

二、RSA加解密与签名验签

一般来说,有两种场景:加密解密和签名验签

加密解密:使用公钥加密,私钥解密

签名验签:使用私钥加密(签名),公钥解密(验签)

例如:B生成一对密钥,向A提供公钥,B保留私钥

加密:防止信息泄露

当A系统传输数据给B系统,担心报文明文传输会导致信息泄露,则可使用公钥对报文进行加密,以防传输过程中信息泄露。B接收加密报文,通过私钥进行解密

签名:防止信息篡改

当B接收后返回消息给A,担心返回消息被修改,A接收到错误消息,则可使用秘钥进行签名,并将签名和返回报文一起发送给A。A通过公钥进行验签,发现签名解析后和返回报文数据一致,证明报文没有被中间拦截篡改

三、代码实现

本例介绍使用秘钥生成PSE证书方式进行加密解密与签名验签的过程

生成一对密钥后,将私钥文件RSA.key上传到SAP服务器,前后需要加标注,否则不能正常使用

ABAP RSA方式调用银行API_加密解密

通过命令生成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
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = lf_plain_input
IMPORTING
buffer = lf_plain_input_x.

"证书域名
wa_recipient_list-id = 'CN=user1'.
APPEND wa_recipient_list TO it_recipient_list.

"加密函数
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.

"展示加密后信息
PERFORM show_data USING lf_output.
SKIP.

CLEAR lv_input_x.
CLEAR lt_recipient_list.
ls_recipient_list-id = 'CN=user1'. " 一般为证书域名
ls_recipient_list-profile = '/tmp/rsa/user1.pse'.
APPEND ls_recipient_list TO lt_recipient_list.

" 解密
CALL FUNCTION '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_x iv_cp = '4110' ).

WRITE:/ lv_input.

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.
签名验签:
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_data TYPE xstring,
lf_output_data TYPE xstring,
lf_inputv_data TYPE xstring,
ls_certificate TYPE ssfcertlin,
lt_certificates TYPE TABLE OF ssfcertlin,
lf_subject(256) TYPE c.

"原文
lv_input = '一段需要处理的报文'.
CALL FUNCTION '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'.
APPEND ls_signer TO lt_signer.

CALL FUNCTION '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 = 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.

PERFORM show_data USING lf_signed_data.
SKIP.

lf_inputv_data = lv_input_x.
" 验签
CLEAR lt_signer.
* verify signature
CALL FUNCTION '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 = 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.
IF sy-subrc <> 0.
* Implement suitable error handling here
WRITE:/ sy-subrc.
ENDIF.


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

WRITE:/ lv_input.


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.

四、简述调用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'.

根据上述签名之后,得到签名字符串拼接到发送报文中ABAP RSA方式调用银行API_加密解密_02

发送数据并获得返回消息即可

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 .

这是一篇站在前人肩膀上完成的博客,各位前辈的资料,给予了本人极大的帮助,尤其感谢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​


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK