目录
一、使用标准函数实现
RSA加密示例-使用公钥字符串加密
RSA加密示例-通过PSE证书文件加密
RSA解密示例-通过PSE证书文件解密
RSA签名验签示例-使用证书签名验签
密钥
参考
注意事项
二、openssl命令行实现
示例代码
SM69配置
参考
三、开源代码实现
Pakage SECF 下的函数组SSFW SSF Functions for Web Services Security
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 = ''."
APPEND ls_recipient_list TO lt_recipient_list.
CALL FUNCTION 'SSFW_KRN_ENVELOPE'
EXPORTING
str_format = 'PKCS1-V1.5'
str_pab = ''
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.
结果验证
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.
结果验证
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.
结果验证
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查看
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.
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