如何於 RPG 中取得 message authentication code(MAC) 碼?
線上交易資料交換頻繁, 前二期, 介紹了 XOR, MD5, 此期介紹
message authentication code(MAC), 這是金融業主機資料傳輸
最常用的資料檢核方法, 於 AS/400 上, 從 V5R2起系統開始提
供產生 MAC 的 API, Calculate MAC (QC3CALMA, Qc3CalculateMAC),範例如下:
File : QRPGLESRC
Member: GENMACR
Type : RPGLE
Usage : CRTBNDRPG GENMACR
OS : V5R2 (若使用上有問題, 請確認 QSYS/QC3CALMA 程式有存在, 若不存在,
請安裝 IBM V5R2 要上 PTF#: SI10060 SI10105)
* if you want use procedure call(Qc3CalculateMAC), you need
* use option 15, create module , then
* CRTPGM PGM(lib/GENMACR) BNDSRVPGM(QC3MAC) and with following
* H Spec and D Spec
H*DEBUG OPTION(*SRCSTMT:*NODEBUGIO)
D*GenMacPr PR ExtProc('Qc3CalculateMAC')
*
H DEBUG OPTION(*SRCSTMT:*NODEBUGIO) DFTACTGRP(*NO) ACTGRP(*CALLER)
H BNDDIR('QC2LE')
D cvthex1To2 PR extproc('cvthc')
D longReceiver * value
D shortSource * value
D receiverBytes 10i 0 value
D cvthex2To1 PR extproc('cvtch')
D shortReceiver * value
D longSource * value
D sourceBytes 10i 0 value
D*GenMacPr PR ExtProc('Qc3CalculateMAC')
D GenMacPr PR ExtPgm('QC3CALMA')
D InpDta 1024
D InpDtaLen 10I 0
D InpDtaFmt 8
D AlgDesc like(ALGD0200)
D AlgdFmt 8
D KeyDesc like(KEYD0200)
D KeyFmt 8
D CrypSrv 1
D CrypDev 10
D MacCode 8
D errcde like(APIERR)
D
D*ALGD0200 algorithm description structure
DALGD0200 DS
D QC3BCA 1 4B 0
D* Block Cipher Alg
D QC3BL 5 8B 0
D* Block Length
D QC3MODE 9 9 inz('1')
D* Mode
D QC3PO 10 10 inz('0')
D* Pad Option
D QC3PC 11 11 inz(x'00')
D* Pad Character
D QC3ERVED 12 12 inz(x'00')
D* Reserved
D QC3MACL 13 16B 0
D* MAC Length
D QC3EKS 17 20B 0
D* Effective Key Size
D QC3IV 21 52
D* Init Vector
D*KEYD0200 key description format structure
DKEYD0200 DS
D* Qc3 Format KEYD0200
D QC3KT 1 4B 0
D* Key Type
D QC3KSL 5 8B 0
D* Key String Len
D QC3KF 9 9 inz('0')
D* Key Format
D QC3ERVED02 10 12 inz(x'000000')
D* Reserved
D QC3KS 13 20
D*
D* variable length
* API error structure
D APIERR DS
D ERRPRV 10I 0 INZ(272)
D ERRLEN 10I 0
D EXCPID 7A
D RSRVD2 1A
D EXCPDT 256A
*
D InpDta S 1024
D InpDtaLen S 10I 0
D InpDtaFmt S 8 inz('DATA0100')
D AlgdFmt S 8 inz('ALGD0200')
D KeyFmt S 8 inz('KEYD0200')
D CrypSrv S 1 inz('1')
D CrypDev S 10
D MacCode S 8
D MacCode4 S 4
D MacHexCode S 8
D DataSrc S 1024
D DataSrcLen S 10I 0
D Icv16 S 16
D Icv08 S 8
D IcvLen S 10I 0
D Key16 S 16
D Key08 S 8
D ErrorMsgId S 7
C *Entry Plist
C Parm DataSrc
C Parm Key16
C Parm Icv16
C Parm MacHexCode
C Parm ErrorMsgId
C
C eval DataSrcLen = %len(%trim(DataSrc))
C If %rem(DataSrcLen : 2) > 0
C eval DataSrc = %trim(DataSrc) + '0'
C EndIf
C
* Convert 2 Hex chars to 1 Char
C callp cvthex2To1 (%addr(InpDta)
C : %addr(DataSrc)
C : %len(%trim(DataSrc)))
C eval QC3BCA = 20
C eval QC3BL = 8
C eval QC3MACL = 8
C eval QC3EKS = 0
C eval Icv16 = %xlate(' ': '0' : icv16)
C callp cvthex2To1 (%addr(Icv08)
C : %addr(Icv16)
C : %len(%trim(Icv16)))
C
C eval QC3IV = Icv08
C eval QC3KT = 20
C eval QC3KSL = 8
C callp cvthex2To1 (%addr(Key08)
C : %addr(Key16)
C : %len(%trim(Key16)))
C eval QC3KS = Key08
C eval InpDtaLen = %len(%trim(InpDta))
C
C Callp GenMacPr(
C InpDta :
C InpDtaLen :
C InpDtaFmt :
C AlgD0200 :
C AlgdFmt :
C KeyD0200 :
C KeyFmt :
C CrypSrv :
C CrypDev :
C MacCode :
C ApiErr )
C If ERRLEN = 0
C eval MacCode4 = MacCode
* Convert 1 Char to 2 Hex chars
C callp cvthex1To2 (%addr(MacHexCode)
C : %addr(MacCode4)
C : %len(MacCode4)* 2)
C eval ErrorMsgId = *Blanks
C Else
C eval MacHexCode = *Blanks
C eval ErrorMsgId = EXCPID
C EndIf
C eval *InLr = *On
測試範例
File : QRPGLESRC
Member: GENMACTEST
Type : RPGLE
Usage : CRTBNDRPG GENMACTEST
CALL GENMACTEST
OS : V5R2
H DEBUG OPTION(*SRCSTMT:*NODEBUGIO) DFTACTGRP(*NO) ACTGRP(*CALLER)
D DataSrc S 1024
D Icv16 S 16
D Key16 S 16
D MacHexCode S 8
D ErrorMsgId S 7
D GenMacR PR ExtPgm('GENMACR')
D DataSrc 1024
D Key16 16
D Icv16 16
D MacHexCode 8
D ErrorMsgId 7
C eval Key16 = 'E07DDB948C3F2D44'
* MACCode: 1BB5AD90
C eval DataSrc =
C '574365400000005000000456655687845'
C eval Icv16 = '20040625105948'
C ExSr GenMacSr
* MACCode: DBB695DD
C eval DataSrc =
C '546646800000010000005644651386983'
C eval Icv16 = '20040625110002'
C ExSr GenMacSr
* MACCode: 1181D5A9
C eval DataSrc =
C '689563200000015000006563232565543'
C eval Icv16 = '20040625110025'
C ExSr GenMacSr
* MACCode: 24AC4268
C eval DataSrc =
C '56989876564645646600000005000310686-
C 8542536988'
C eval Icv16 = '20040625110212'
C ExSr GenMacSr
* MACCode: 00FC6820
C eval DataSrc =
C '65523591235858665400000015000110511-
C 3235463238'
C eval Icv16 = '20040625110220'
C ExSr GenMacSr
* MACCode: FBC4650E
C eval DataSrc =
C '65522332325465384100000010000110122-
C 4323235858'
C eval Icv16 = '20040625110232'
C ExSr GenMacSr
* MACCode: 23B09440
C eval DataSrc =
C '104117700000000600000112011274664'
C eval Icv16 = '20050725101431'
C ExSr GenMacSr
* MACCode: 5E8104EC
C eval DataSrc =
C '222759300000000300002792020001542'
C eval Icv16 = '20050725101549'
C ExSr GenMacSr
C eval *InLr = *On
C**********************************************************************
C GenMacSr BegSr
C eval MacHexCode = *Blanks
C eval ErrorMsgId = *Blanks
C Callp GenMacR(
C DataSrc :
C Key16 :
C Icv16 :
C MacHexCode :
C ErrorMsgId )
C
C If ErrorMsgId = *Blanks
C MAcHexCode Dsply
C Else
C ErrorMsgId Dsply
C EndIf
C EndSr
C**********************************************************************
A blog about IBM i (AS/400), MQ and other things developers or Admins need to know.
星期一, 11月 06, 2023
2005-04-18 如何於 RPG 中取得 message authentication code(MAC) 碼?
2004-08-02 如何於 AS/400 直接加解密資料?API Qc3EncryptData, Qc3DecryptData
如何於 AS/400 直接加解密資料?API Qc3EncryptData, Qc3DecryptData
Cryptographic Services
https://www.ibm.com/docs/en/i/7.5?topic=category-cryptographic-services-apis
要於 AS/400 執行加解密功能,於
V5R2 要上 PTF#: SI10060 SI10105,
V5R3 已內含,以下是程式範例:
File : QRPGLESRC
Member: DECRYPTDTA
Type : RPGLE
* CRTRPGMOD DECRYPTDTA
* CRTPGM PGM(VENGOAL/DECRYPTDTA) BNDSRVPGM(QC3DTAEN QC3PRNG)
*
* Encrypt Data (OPM, QC3ENCDT; ILE, Qc3EncryptData) API
* Service Program Name: QC3DTAEN
* Decrypt Data (OPM, QC3DECDT; ILE, Qc3DecryptData) API
* Service Program Name: QC3DTADE
H DEBUG OPTION(*SRCSTMT:*NODEBUGIO)
*/copy qsysinc/qrpglesrc.QC3CCI
D*******************************************************************
D*Data definitions
D*******************************************************************
D*ALGD0200 algorithm description structure
DQC3D0200 DS
D* Qc3 Format ALGD0200
D QC3BCA 1 4B 0
D* Block Cipher Alg
D QC3BL 5 8B 0
D* Block Length
D QC3MODE 9 9
D* Mode
D QC3PO 10 10
D* Pad Option
D QC3PC 11 11
D* Pad Character
D QC3ERVED 12 12
D* Reserved
D QC3MACL 13 16B 0
D* MAC Length
D QC3EKS 17 20B 0
D* Effective Key Size
D QC3IV 21 52
D* Init Vector
D*ALGD0300 algorithm description structure
DQC3D0300 DS
D* Qc3 Format ALGD0300
D QC3SCA 1 4B 0
D* Stream Cipher Alg
D*ALGD0400 algorithm description structure
DQC3D0400 DS
D* Qc3 Format ALGD0400
D QC3PKA 1 4B 0
D* Public Key Alg
D QC3PKABF 5 5
D* PKA Block Format
D QC3ERVED00 6 8
D* Reserved
D QC3SHA 9 12B 0
D* Signing Hash Alg
D*ALGD0500 algorithm description structure
DQC3D0500 DS
D* Qc3 Format ALGD0500
D QC3HA 1 4B 0
D* Hash Alg
D*DATA0200 array data format structure
DQC3A0200 DS
D* Qc3 Format DATA0200
D QC3DP 1 16*
D* Data Ptr
D QC3DL 17 20B 0
D* Data Len
D QC3ERVED01 21 32
D* Reserved
D*KEYD0200 key description format structure
DQC3D020000 DS
D* Qc3 Format KEYD0200
D QC3KT 1 4B 0
D* Key Type
D QC3KSL 5 8B 0
D* Key String Len
D QC3KF 9 9
D* Key Format
D QC3ERVED02 10 12 inz(x'000000')
D* Reserved
D*QC3KS 13 13
D*
D* variable length
D*******************************************************************
* API error structure
D APIERR DS
D ERRPRV 10I 0 INZ(272)
D ERRLEN 10I 0
D EXCPID 7A
D RSRVD2 1A
D EXCPDT 256A
D
*Encrypt Data (OPM, QC3ENCDT; ILE, Qc3EncryptData) API protects
*data privacy by scrambling clear data into an unintelligible form.
D*Qc3EncryptData Pr ExtProc('Qc3EncryptData')
D Qc3EncryptData Pr ExtPgm('QC3ENCDT')
D clrDta 32767a
D clrDtaLen 10I 0
D clrDtaFmt 8
D algorithm like(QC3D0200)
D algorithmFmt 8
D key like(KeyC)
D keyFmt 8
D srvProvider 1
D deviceName 10
D encryptedData 32767a
D encryptedBufL 10I 0
D encryptedRtnL 10I 0
D errcde like(APIERR)
* Decrypt Data (OPM, QC3DECDT; ILE, Qc3DecryptData) API restores
* encrypted data to a clear (intelligible) form.
D*Qc3DecryptData Pr ExtProc('Qc3DecryptData')
D Qc3DecryptData Pr ExtPgm('QC3DECDT')
D encryptedData 32767a
D encryptedDtaL 10I 0
D algorithm like(QC3D0200)
D algorithmFmt 8
D key like(keyC)
D keyFmt 8
D srvProvider 1
D deviceName 10
D clrDta 32767a
D clrDtaBufL 10I 0
D clrDtaRtnL 10I 0
D errcde like(APIERR)
DQc3GenPRNs Pr ExtPRoc('Qc3GenPRNs')
D PrnDta 512
D PrnDtaLen 10I 0
D PrnType 1
D PrnParity 1
D errcde like(APIERR)
D PrnDta S 512
D PrnDtaLen S 10I 0
D PrnType S 1 inz('1')
D PrnParity S 1 inz('1')
D clrDta S 32767a
D clrDtaLen S 10I 0
D clrDtaFmt S 8 inz('DATA0100')
D algorithm S like(QC3D0200)
D algorithmFmt S 8 inz('ALGD0200')
D key S like(KeyC)
D keyFmt S 8 inz('KEYD0200')
D srvProvider S 1 inz('1')
D deviceName S 10 inz(*blanks)
D encryptedData S 32767a
D encryptedDtaL S 10I 0
D encryptedBufL S 10I 0
D encryptedRtnL S 10I 0
D clrDtaBufL S 10I 0
D clrDtaRtnL S 10I 0
D KeyString S 256
D KeyC S 256
C Eval clrDta = 'This is a test.'
C Eval clrDtaLen = %len(%trim(clrDta))
C Eval encryptedBufL = %size(encryptedData)
C* Block cipher algorithm
* 20 DES
* 21 Triple DES
* 22 AES
C Eval QC3BCA = 20
*Block length
* 8 DES
* 8 Triple DES
* 16 AES
C Eval QC3BL = 8
*Mode
* 0 ECB
* 1 CBC
* 2 OFB. Not valid with AES.
* 3 CFB 1-bit. Not valid with AES.
* 4 CFB 8-bit. Not valid with AES.
* 5 CFB 64-bit. Not valid with AES
C Eval QC3MODE = '1'
* Pad Option
* 0 No padding is performed.
* 1 Use the character specified in the pad character field for padding
* 2 The pad counter is used as the pad character.
C Eval QC3PO = '1'
* Pad Character
C Eval QC3PC = X'00'
* Reserved
C Eval QC3ERVED = X'00'
* MAC Length
* This field is not used on an encrypt operation and must be set to
* null(binary 0s).
C Eval QC3MACL = X'00000000'
* Effective key size
* This field must be set to 0.
C Eval QC3EKS = 0
* Initialization vector
* The initialization vector (IV). An IV is not used for mode ECB,
* and must be set to NULL (binary 0s).
C Eval QC3IV = *AllX'00'
C Reset encryptedData
C Eval encryptedBufL = %len(encryptedData)
C* Eval algorithm = %addr(QC3D0200)
C Eval algorithm = QC3D0200
* Key Type KeyFormat KeyLength
* 20 DES 0 8(7 bits used,rightmost setbit
* 21 Triple DES 0 8,16,24(7 bits used,rightmost setbit
* 22 AES 0 16,24,32
* 30 RC4-compatible 0 1<->256
* 50 RSA public 1
* 51 RSA private 1
C Eval QC3KT = 20
* Key Format
C Eval QC3KF = '0'
* Key String
C Eval KeyString = '12345678'
C* Eval PrnDtaLen = 8
C* callP Qc3GenPRNs(
C* PrnDta :
C* PrnDtaLen :
C* PrnType :
C* PrnParity :
C* APIERR
C* )
C* ExSr ChkErrCde
C* Eval KeyString = %SubSt(PrnDta :
C* 1 : PrnDtaLen)
* Key Length
C Eval QC3KSL = %len(%trim(KeyString))
C Eval KeyC = QC3D020000 + %trim(KeyString)
C* Eval Key = %addr(KeyC)
C Eval Key = KeyC
C callP Qc3EncryptData(
C clrDta :
C clrDtaLen :
C clrDtaFmt :
C algorithm :
C algorithmFmt :
C key :
C keyFmt :
C srvProvider :
C deviceName :
C encryptedData :
C encryptedBufL :
C encryptedRtnL :
C APIERR
C )
C ExSr ChkErrCde
C Reset clrDta
C Eval encryptedDtaL = encryptedRtnL
C Eval clrDtaBufL = %size(clrDta)
C callP Qc3DecryptData(
C encryptedData :
C encryptedDtaL :
C algorithm :
C algorithmFmt :
C key :
C keyFmt :
C srvProvider :
C deviceName :
C clrDta :
C clrDtaBufL :
C clrDtaRtnL :
C APIERR
C )
C ExSr ChkErrCde
C dump
C Eval *InLr = *On
**********************************************************************
C ChkErrCde BegSr
C If ERRLEN > 0
C EXCPID DSPLY
C EndIf
C EndSr
訂閱:
文章 (Atom)