sumu-ning / aes Goto Github PK
View Code? Open in Web Editor NEWABAP Utilities for AES/Rijndael encryption, decryption
License: MIT License
ABAP Utilities for AES/Rijndael encryption, decryption
License: MIT License
I have a requirement where I must decrypt a file that in SAP that has been encrypted with aes-256-cbc protocol. The file is encrypted with a fixed KEY and IV. I've already implemented all classes from this Git repo, test class also works fine so basically I'm ready to go. Unfortunately I haven't come to the point where I can start using the classes to really decrypt the data yet.
I'm able to decrypt the file via openSSL, so I'm sure it's possible to successfully decrypt the file. However, in ABAP I'm quite unsuccessful until now, probably because I'm completely new to encryption/decryption and still quite new to ABAP too. When I try to read the data from the file (file is placed on the app.server from where I should read it), I open a dataset in text mode with non-unicode encoding. I read the data into a variable lv_data which has type string (see code snippet below).
TRY.
OPEN DATASET lv_filepath FOR INPUT IN TEXT MODE ENCODING NON-UNICODE.
DO.
READ DATASET lv_filepath INTO lv_str.
IF sy-subrc NE 0.
EXIT.
ENDIF.
lv_data = |{ lv_data }{ lv_str }|.
ENDDO.
CATCH cx_root.
ENDTRY.
When I open the encrypted file with notepad it looks like this:
When the data is read into parameter lv_data (type string) in SAP it looks like this. Could it be that I'm messing something up with the data types?
Any help is much appreciated, thanks a lot in advance!
Hi, thanks for adding the CBC support to your library, now I can successfully decrypt AES-encrypted strings (in base64) coming from OpenSSL. There seems to be a bug though somewhere. I do the following steps:
First, I get the key and init. vector for the password from OpenSSL:
openssl aes-256-cbc -nosalt -P -pass pass:unserGeheimesPasswort
Then I encrypt a string using that same password:
echo geheime_Kundendaten | openssl enc -aes-256-cbc -a -nosalt -pass pass:unserGeheimesPasswort
In ABAP I decode that encrypted base64-encoded string:
CALL FUNCTION 'SCMS_BASE64_DECODE_STR'
EXPORTING
input = p_data "base64-encoded, encrypted AES string: geheime_Kundendaten
unescape = 'X'
IMPORTING
output = lv_x_data.
Then I decrypt that string via your class:
CALL METHOD lr_aes_util->decrypt_xstring(
EXPORTING
i_data = lv_x_data
i_key = lv_x_key
i_initialization_vector = lv_x_iv
i_encryption_mode = 'CBC'
IMPORTING
e_data = lv_x_result ).
That method call returns the correctly decrypted string, which I have encrypted via OpenSSL before. However, there are some additional bytes as suffix. In the ABAP debugger the value of lv_x_result
is
67656865696D655F4B756E64656E646174656E200D0A0A0A0A0A0A0A0A0A0A0A
which, after converting the xstring to binary via SCMS_XSTRING_TO_BINARY
and from binary to string via SCMS_BINARY_TO_STRING
results in
geheime_Kundendaten ############
So the first part is correct, but these trailing ############
should not be there. When I remove all the 0D0A
bytes (Carriage Return / Line Feed) from the xstring, then the result is correct.
Now, is this a bug in your code, or do I need an additional step to decrypt AES-CBC correctly?
Hi,
I am working on implementing OpenPGP in ABAP
https://github.com/larshp/abapPGP
https://tools.ietf.org/html/rfc4880
And will eventually need AES encryption, and I have found your nice AES library 👍
In order to make it easier to install, have you considered using abapGit, and will you accept a pull request which changes the format to abapGit format?
You can take a look at https://github.com/larshp/abapPGP for how abap code in abapGit format looks like in a git repository.
Suggest using built-in types instead of referring to DDIC data elements, this will make sure the code works across more systems, following are candiates to be changed
DTEL BOOLE_D
DTEL CHAR10
DTEL HEXTYP
DTEL INT1
DTEL INT4
use abap_bool
, type c length 10
, type x length 1
etc., if needed the types can be defined in a interface
my string:
{"transactionID":"175738861574757193070","status":"SUCCESS","paymentBy":"INTERNET BANKING","contractNo":"GEMC-11687717573886","gemInvoiceNo":"GEM-61550","invoiceNo":"3131","billNo":"511687717573886-1B1","billAmountPaid":"391108.00","transactionDate":"2020-03-02","deductedAmount":"0","deductionType":"LD/TDS","bankName":"SBI","chequeNumber":"","bankTransactionNo":"SBIUATTEST1234","demandDraftNo":"","sanctionNo":"","sanctionDate":""}
my key: qcNv4GRqj40WdqhY
iam using ECB128/PKCS5PADDING
zcl_aes_utility=>encrypt_xstring(
exporting
i_key = i_key_xstring
i_data = i_xstring
i_padding_standard = ZCL_PADDING_UTILITY_PKCS_5=>MC_PADDING_STANDARD_PKCS_5
i_encryption_mode = zcl_aes_utility=>mc_encryption_mode_ecb "mode
importing
e_data = lv_message ).
iam getting:
HmS6lVtVWBJRkPozvNUFU4uF7/ihCQT64oE3TaMF2pqGW4MK1Kr+bq2IaxVOVGCwe72sotxVC+H88qeAQXnUpCdVlUFUsWg7d73vqnw7IbUhSJnBQ+7mfhNz2FdSuxGfyAIzlxMJBxSP0Lz1gF5m98Xd1VdUpivc1GvxacrLqRWmm+TIr63nm2WzSiR3WE8P2Oy+gK/VIrInDaliVEnPbsu0Tfpd1+0RX85AiAcRsh4xpUEpM1f2e0lVCfDcrd3ooy5CEjHGMLUjImIix3rMCwyv4dBV1YDGPWiUd4X+Nedd+lh1+ROk5gQtlw2juCipxhXFFgIA0sfHuHJRACm53oJWTm45S8rbBFs6ygDaDK0lMe/DfAT1lvhwIVG69X5S6t8EVpL1RTmmFINX4b+zsbDnlV1dfBfUXsnX+wjDWgEo1Tk1TTKoo6tRHunAQs8ZmK31lx4oxl5SD5QQ2uwKg7zu38beXTUAYTXDim5qyRHZ536VnN7iXP30FGpHaUIMHvxIb7G5DnBURGIafOYotaKQ8W8wUo2fYOd3GMFyHja1iaLVavr/BttVTOrvqDKlFw7tLK//nTTqBqGNA9nTNg==
whereas online tool at [https://www.devglan.com/online-tools/aes-encryption-decryption] is showing:
HmS6lVtVWBJRkPozvNUFU4uF7/ihCQT64oE3TaMF2pqGW4MK1Kr+bq2IaxVOVGCwe72sotxVC+H88qeAQXnUpCdVlUFUsWg7d73vqnw7IbUhSJnBQ+7mfhNz2FdSuxGfyAIzlxMJBxSP0Lz1gF5m98Xd1VdUpivc1GvxacrLqRWmm+TIr63nm2WzSiR3WE8P2Oy+gK/VIrInDaliVEnPbsu0Tfpd1+0RX85AiAcRsh4xpUEpM1f2e0lVCfDcrd3ooy5CEjHGMLUjImIix3rMCwyv4dBV1YDGPWiUd4X+Nedd+lh1+ROk5gQtlw2juCipxhXFFgIA0sfHuHJRACm53oJWTm45S8rbBFs6ygDaDK0lMe/DfAT1lvhwIVG69X5S6t8EVpL1RTmmFINX4b+zsbDnlV1dfBfUXsnX+wjDWgEo1Tk1TTKoo6tRHunAQs8ZmK31lx4oxl5SD5QQ2uwKg7zu38beXTUAYTXDim5qyRHZ536VnN7iXP30FGpHaUIMHvxIb7G5DnBURGIafOYotaKQ8W8wUo2fYOd3GMFyHja1iaLVavr/BttVTOrvqDKlKfxb5PoFsX2FsS1vGmTUVQ==
we need to send an encrypted text to a destination, where message will be decrypted, processed and response will be sent back.
encrypted message through zcl_aes_utility was showing an error at receiver side.
encrypted message through online tool has worked properly as expected.
difference between above 2 encrypted messages is last 24 characters.
Please let me know if iam missing anything during encryption
Hi @Sumu-Ning,
I would like to rename the classes so everything is prefixed with "ZCL_AES_", my suggestion:
rename ZCL_BYTE_PADDING_UTILITY to ZCL_AES_PADDING
rename ZCL_PADDING_UTILITY_NONE to ZCL_AES_PADDING_NONE
rename ZCL_PADDING_UTILITY_PKCS_5 to ZCL_AES_PADDING_PKCS_5
rename ZCL_PADDING_UTILITY_PKCS_7 to ZCL_AES_PADDING_PKCS_7
rename ZCL_RIJNDAEL_UTILITY to ZCL_AES_RIJNDAEL
suggest creating custom exception class instead of reusing CX_ME_ILLEGAL_ARGUMENT
The exception is from package "Mobile: Core Components", application component BC-MOB. By having a custom exception class we can remove this dependency
Hi,
Another idea, what do you think about introducing a factory class eg class ZCL_AES_FACTORY with 2 methods:
CREATE_MODE returns reference to ZIF_AES_MODE
CREATE_PADDING returns reference to new interface ZIF_AES_PADDING
This would also change ENCRYPT_XSTRING so it takes a reference to ZIF_AES_MODE and ZIF_AES_PADDING instead of the constants.
Advantages:
Seems the ZCL_RIJNDAEL_UTILITY not always generate the same data for all the blocks
For example:
Key:
000102030405060708090A0B0C0D0E0F
PlainText:
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
CipherText:
C6A13B37878F5B826F4F8162A1C8D879
103F26CFB99ADF9E48C8ACD130A0A4FD
103F26CFB99ADF9E48C8ACD130A0A4FD
103F26CFB99ADF9E48C8ACD130A0A4FD
Seems the initilization round of later blocks are missing or something.
However, the ZCL_AES_UTILITY class is using only the first block, so it is still good to use.
Hi,
I find this code really useful but am struggling to understand where I am going wrong.
I am trying to encrypt with the following details
PKCS5 PAdding.
Cipherkey - 5545427A64334A6B49314E555255564D
I have written code as follows
`CALL METHOD zcl_aes_utility=>encrypt_xstring
EXPORTING
i_key = lv_cipherkey
i_data = lv_plaintext
* i_initialization_vector = i_iv
i_padding_standard = zcl_aes_utility=>mc_padding_standard_pkcs_5
i_encryption_mode = zcl_aes_utility=>mc_encryption_mode_ecb
IMPORTING
e_data = lv_ciphertext.`
CALL FUNCTION 'SCMS_BASE64_ENCODE_STR'
EXPORTING
input = lv_ciphertext
IMPORTING
output = lv_encrypted.
My plain text is '7B227472616E73616374696F6E4944223A22333039323230313031353739313739343330393730222C22737461747573223A2253756363657373222C227061796D656E744279223A225341505F46554E4331222C22636F6E74726163744E6F223A2247454D432D353131363837373330393232373530222C2267656D496E766F6963654E6F223A2247454D2D3634303139222C22696E766F6963654E6F223A223736746768222C2262696C6C4E6F223A223531313638373733303932323735302D334231222C2262696C6C416D6F756E7450616964223A22373330302E3030222C227472616E73616374696F6E44617465223A22323032302D30312D3136222C226465647563746564416D6F756E74223A22302E303020222C22646564756374696F6E54797065223A22222C2262616E6B4E616D65223A224943494349222C226368657175654E756D626572223A22222C2262616E6B5472616E73616374696F6E4E6F223A22313233343332222C2264656D616E6444726166744E6F223A22222C2273616E6374696F6E4E6F223A22222C2273616E6374696F6E44617465223A22227D'
However, when i get the encoded string, it shows as below
IUEgq2A30lHwd/tf97TBvuiYKKPj5XjmGwLru5ueFBqdAkZm7M7Di0poHr1FObd2MqEcR/GJvPrcF8hw3rpFQq0SV9tdXP1wctG4s5uf0tppraJHXSI1Vluq/FHhdTHVvxvseg4bQ1671DYIW5tFJ0HCRpm79T8d9XAycgqmb6E4US7v5NP5+420NPIwpQGWDqUV9e8/kdzAhUtTjXZmY8HRS7T5WUgL2pkc6zWbFGKoKrJ9M/TP0IF4puI0oBrFUzmi4ipP74gSo4K+1NvwUhK9pgWXXLggvOyCj62Xu7Gz8r177mR2rMLUQVgI5RmM+yO3lAFUeFyPw8plWo74aTdkdejtBx7VeLlrvi1pXD+m6X7/uasr7AgfRaIlY9sHxqvId11v5zURY7pEVWEF6oODp1bh8o3SKpHhX74KUONJkmEVeVXvuB+QHggJnWNFVzPCg9AOOH8F9BhgY+L5b5gyUnsxrEuioSpamY7WXarQYey8qK+039R+JmZUUW1OwWecPJBCp5gtyIDuiM5FK1IlL7vQaKyv/IHSrCLM+c/iS2Gm2XCuwD1r4Hr/U4Bo
And when i use online tools like https://www.devglan.com/online-tools/aes-encryption-decryption, i get
IUEgq2A30lHwd/tf97TBvuiYKKPj5XjmGwLru5ueFBqdAkZm7M7Di0poHr1FObd2MqEcR/GJvPrcF8hw3rpFQq0SV9tdXP1wctG4s5uf0tppraJHXSI1Vluq/FHhdTHVvxvseg4bQ1671DYIW5tFJ0HCRpm79T8d9XAycgqmb6E4US7v5NP5+420NPIwpQGWDqUV9e8/kdzAhUtTjXZmY8HRS7T5WUgL2pkc6zWbFGKoKrJ9M/TP0IF4puI0oBrFUzmi4ipP74gSo4K+1NvwUhK9pgWXXLggvOyCj62Xu7Gz8r177mR2rMLUQVgI5RmM+yO3lAFUeFyPw8plWo74aTdkdejtBx7VeLlrvi1pXD+m6X7/uasr7AgfRaIlY9sHxqvId11v5zURY7pEVWEF6oODp1bh8o3SKpHhX74KUONJkmEVeVXvuB+QHggJnWNFVzPCg9AOOH8F9BhgY+L5b5gyUnsxrEuioSpamY7WXarQYey8qK+039R+JmZUUW1OwWecPJBCp5gtyIDuiM5FK1IlL7vQaKyv/IHSrCLM+c/6S/NxlgIM1Q1HZM4XlL0W
If you see, the encoded result is same except for the last 21 characters. I do not know how to the the last 21 characters to match the result from devglan site.
Perhaps something wrong with padding which I am unable to identify. I've been thinking about this in my sleep lol.
Before calling the encrypt, i do the following
` CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = lv_key
encoding = '4110'
IMPORTING
buffer = lv_cipherkey
EXCEPTIONS
failed = 1
OTHERS = 2.
IF sy-subrc <> 0.
* gv_er_msg = 'Error while Binary conversion of key'(010).
* RAISE EXCEPTION TYPE cx_alert_cat_exists.
ENDIF.`
` CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = lv_paydata
encoding = '4110'
IMPORTING
buffer = lv_plaintext
EXCEPTIONS
failed = 1
OTHERS = 2.
IF sy-subrc <> 0.
* gv_er_msg = 'Error while Binary conversion of key'(010).
* RAISE EXCEPTION TYPE cx_alert_cat_exists.
ENDIF.`
Can you please guide me as to what I might be missing?
Thank you.
S
Hi, are there any quick ABAP usage examples with this library anywhere? Am keen to give it a try, but wondering where to start... Thanks :)
Following are the public methods in class ZCL_AES_UTILITY,
IS_VALID_KEY_XSTRING
IS_VALID_IV_XSTRING
ENCRYPT_XSTRING
DECRYPT_XSTRING
ENCRYPT_RAW16_TABLE
DECRYPT_RAW16_TABLE
CONVERT_XSTRING_TO_RAW16_TABLE
CONVERT_RAW16_TABLE_TO_XSTRING
VALIDATE_ENCRYPTION_MODE
VALIDATE_PADDING_STANDARD
VALIDATE_RAW16_TABLE_SIZE
ADD_PADDING_RAW16_TABLE
REMOVE_PADDING_RAW16_TABLE
I guess only ENCRYPT_XSTRING and DECRYPT_XSTRING is used by applications, so I suggest changing the rest to private.
The padding used x00 up to the block boundary is incorrect. AES CBC is supposed to use PKCS#7 padding. There is actually a chance of losing data when removing x00 based on this padding approach apara from the fact that it is the wrong padding.
The pkcs 7 padding in simple terms is:
bytes needed to fill last block / padding to use
01
0202
030303
04040404
etc to
0E............0E for padd 15 bytes
and
importantly
of the plain text actually plain hex is a better description is a multiple of the block size
and although no padding would appear to be necessary, a complete extra block is required with
1010101010......10 16 times for 16 byte block size
This is important if 2 systems are to share messages successfully. The Padding needs to be consistent and correct.
Hi, I have a string encrypted via OpenSSL command line:
echo "0075266945" | openssl enc -aes-256-cbc -a -nosalt -pass pass:TUA_DKK_CCIP_PW
H6xgbzDoj091wZjAj+mvKA==
This encrypted string "H6xgbzDoj091wZjAj+mvKA==" is stored in an ABAP string variable. According to a previous ticket here on GitHub I do the following: First call function SCMS_BASE64_DECODE_STR
like so:
"Convert payload from Base64 to Hex
CALL FUNCTION 'SCMS_BASE64_DECODE_STR'
EXPORTING
input = i_encrypted_data
unescape = 'X'
IMPORTING
output = lv_x_data.
Then I decrypt the string via your tool:
"Then decrypt the payload using the encryption key and init. vector, all in xstring format
CALL METHOD lr_aes_util->decrypt_xstring(
EXPORTING
i_data = lv_x_data
i_key = lv_x_key "CAE47A6067F0F2DCC728AF877530529038035761C89E0636DB043A6FE6815F04
i_initialization_vector = lv_x_iv "4BBF93F6535EC0AD41CBDEB346719675
i_encryption_mode = i_encryption_mode
IMPORTING
e_data = lv_x_result ).
Then I remove the trailing CR/LF bytes:
DO.
lv_len = xstrlen( lv_x_result ) - 1.
IF lv_len = -1.
EXIT.
ENDIF.
IF lv_x_result+lv_len(1) <= lc_byte_ws.
"remove trailing non-printable character
lv_x_result = lv_x_result(lv_len).
ELSE.
EXIT.
ENDIF.
ENDDO.
And the last steps:
"Finally convert the decrypted binary xstring back to a string again
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_x_result
IMPORTING
output_length = lv_len
TABLES
binary_tab = lt_data.
CALL FUNCTION 'SCMS_BINARY_TO_STRING'
EXPORTING
input_length = lv_len
IMPORTING
text_buffer = lv_result
TABLES
binary_tab = lt_data.
MOVE lv_result TO r_decrypted_data.
However, now in r_decrypted_data
the wrong data is stored: MF¬ö�í«a6Š©w
Is this a bug in your library, or am I doing something wrong here?
Hi,
I'm new to ABAP, appreciate if you can help to pen down what needs to be done to have AES 128 CBC encryption? There are many class file, do I have to create all in SAP? Do you have sample program to do encryption?
Thanks in advance
AES 盐值 解密。怎么调用呢?
DECRYPT_IV
https://blogs.sap.com/2019/08/26/aes-encryption-in-abap/
https://www.soinside.com/question/kXANQ2vSqP4xbcyBXD2sqR
I am really interested in your library, but I am having a hard time using it with normal ABAP string variables. Converting from and to xstring basically works, but I cannot decrypt a string that have been encrypted via OpenSSL.
Do you have any examples on how to use your library with OpenSSL-encrypted strings?
Hi Everyone,
I did several tests but cannot decrypt same result from https://www.devglan.com/online-tools/aes-encryption-decryption
It is like decrpting first 2 chars and it is matching. Where is the error ? Is it online tool causing the issue , because they didin't mention what padding they are using.
I just want a simple test which i can encrypt from ABAP but decrypt from online tool with same key.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.