Encrypt data in a byte array using the specified block cipher algorithm, mode and padding. The key and initialization vector are passed as byte arrays.
Public Declare Function CIPHER_EncryptBytes Lib "diCrPKI.dll" (ByRef lpOutput As Byte, ByVal nOutBytes As Long, ByRef lpInput As Byte, ByVal nInputLen As Long, ByRef lpKey As Byte, ByVal nKeyLen As Long, ByRef lpIV As Byte, ByVal nIvLen As Long, ByVal strAlgModePad As String, ByVal nOptions As Long) As Long
nRet = CIPHER_EncryptBytes(lpOutput(0), nOutBytes, lpInput(0), nInputLen, lpKey(0), nKeylen, lpIV(0), nIvLen, strAlgModePad, nOptions)
long __stdcall CIPHER_EncryptBytes(unsigned char *lpOutput, long nOutBytes, const unsigned char *lpInput, long nInputLen, const unsigned char *lpKey, long nKeyLen, const unsigned char *lpIV, long nIvLen, const char *szAlgModePad, long nOptions);
NULL
for ECB mode.If successful, the return value is the number of bytes required in the output; otherwise it returns a negative error code.
Public Function cipherEncryptBytes
(lpInput() As Byte, lpKey() As Byte, lpIV() As Byte, szAlgModePad As String, Optional nOptions As Long = 0) As Byte()
Cipher.Encrypt Method (Byte[], Byte[], Byte[], CipherAlgorithm, Mode, Padding, Cipher.Opts)
static bvec_t dipki::Cipher::Encrypt (const bvec_t &data, const bvec_t &key, const bvec_t &iv, Alg alg, Mode mode=Mode::ECB, Padding pad=Padding::Default, Opts opts=Opts::None)
static bvec_t dipki::Cipher::Encrypt (const bvec_t &data, const bvec_t &key, const bvec_t &iv, const std::string algModePad, Opts opts=Opts::None)
static Cipher.encrypt_block(data, key, iv=None, alg=Alg.TDEA, mode=Mode.ECB)
static Cipher.encrypt(data, key, iv=None, algmodepad='', alg=None, mode=Mode.ECB, pad=Pad.DEFAULT, opts=Opts.DEFAULT)
static Cipher.encrypt_block(data, key, iv=None, alg=Alg.TDEA, mode=Mode.ECB)
Padding is added as specified to the input before encryption. The user must allocate an output buffer of the required length, which will always be at least as long as the input, or longer if padding is to be added.
The algorithm/mode/padding must be specified using either the szAlgModePad string or nOptions parameter, but not both (see Specifying the algorithm, mode and padding for generic block cipher functions). The length of key lpKey must be exactly the required key size, and the length of the IV, if required, exactly the block size. See Valid key and block sizes.
If nOutBytes is set to zero or lpOutput set to 0 (or NULL
in C or ByVal 0&
in VBA),
the required number of bytes will be returned.
If the NoPadding option is specified, the required output length will be the same as the input.
Defaults: If padding is not specified then the default padding method depends on the cipher mode:
pkcs5padding will be used for ECB and CBC mode and nopadding for all other modes.
The default cipher mode is ECB.
Thus "aes128"
is the same as "aes128/ecb/pkcs5padding"
.
Note that padding is only needed for ECB or CBC mode where the input length is not a multiple of the block size.
It is an error (BAD_LENGTH_ERROR
) to specify NoPadding with ECB or CBC mode if the length of the input
is not an exact multiple of the block size.
The padding option is ignored for CTR, OFB and CFB modes, which do not need padding.
The default nopadding is always used for these modes regardless of what is specified
(so just use the default, e.g. "aes128/ctr"
).
[New in v12.3]
Use the PKI_IV_PREFIX to prepend the IV before the ciphertext in the output.
This will add the IV before the ciphertext in the form IV||CT
.
This is the scheme used with block ciphers in XML encryption (see section 5.2 of [XMLENC])
where they use the phrase "The resulting cipher text is prefixed by the IV."
It is the responsibility of the receiver to parse this data to recover the IV.
Dim key() As Byte Dim iv() As Byte Dim pt() As Byte Dim ct() As Byte Dim ok() As Byte Dim ptlen As Long Dim ctlen As Long Dim keylen As Long Dim ivlen As Long Dim algstr As String algstr = "Aes128/CBC/OneAndZeroes" Debug.Print algstr key = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687") iv = cnvBytesFromHexStr("FEDCBA9876543210FEDCBA9876543210") keylen = UBound(key) + 1 ivlen = UBound(iv) + 1 Debug.Print "KY=" & cnvHexStrFromBytes(key) Debug.Print "IV=" & cnvHexStrFromBytes(iv) ' "Now is the time for all good men to" pt = cnvBytesFromHexStr("4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F") ptlen = UBound(pt) + 1 ' Correct result ok = cnvBytesFromHexStr("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B") Debug.Print ("PT=" & cnvHexStrFromBytes(pt)) Debug.Print ("PT='" & StrConv(pt, vbUnicode) + "'") ' 1. Find out how long an output buffer we need ctlen = CIPHER_EncryptBytes(0, 0, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, 0) Debug.Print "CIPHER_EncryptBytes returns " & ctlen ' 2. Allocate the buffer ReDim ct(ctlen - 1) ' 3. Encrypt to output buffer ctlen = CIPHER_EncryptBytes(ct(0), ctlen, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, 0) Debug.Print "CT=" & cnvHexStrFromBytes(ct) Debug.Print "OK=" & cnvHexStrFromBytes(ok) ' PART 2 - prefix the IV in the output ctlen = CIPHER_EncryptBytes(0, 0, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, PKI_IV_PREFIX) Debug.Print "CIPHER_EncryptBytes(PKI_IV_PREFIX) returns " & ctlen ReDim ct(ctlen - 1) ctlen = CIPHER_EncryptBytes(ct(0), ctlen, pt(0), ptlen, key(0), keylen, iv(0), ivlen, algstr, PKI_IV_PREFIX) Debug.Print "IV||CT=" & cnvHexStrFromBytes(ct)
This should result in output as follows:
Aes128/CBC/OneAndZeroes KY=0123456789ABCDEFF0E1D2C3B4A59687 IV=FEDCBA9876543210FEDCBA9876543210 PT=4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F PT='Now is the time for all good men to' CIPHER_EncryptBytes returns 48 CT=C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B OK=C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B
[New in v12.3] Use the PKI_IV_PREFIX option to prepend the IV to the ciphertext in the output.
CIPHER_EncryptBytes(PKI_IV_PREFIX) returns 64 IV||CT=FEDCBA9876543210FEDCBA9876543210C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B <------IV (16 bytes)-----------><--------CT (48 bytes)------------------------------------------------------------------------->
For another example of using PKI_IV_PREFIX see the second example in CIPHER_DecryptBytes.
Dim key() As Byte Dim iv() As Byte Dim pt() As Byte Dim ct() As Byte Dim dt() As Byte Dim algstr As String ' PART 1 algstr = "Aes128/CBC/OneAndZeroes" Debug.Print algstr key = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687") iv = cnvBytesFromHexStr("FEDCBA9876543210FEDCBA9876543210") ' "Now is the time for all good men to" pt = cnvBytesFromHexStr("4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F") ct = cipherEncryptBytes(pt, key, iv, algstr, 0) Debug.Print "CT=" & cnvHexStrFromBytes(ct) Debug.Print "OK=C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E1771D4CDA34FBFB7E74B321F9A2CF4EA61B" dt = cipherDecryptBytes(ct, key, iv, algstr, 0) Debug.Print "dt='" & StrConv(dt, vbUnicode) & "'" ' PART 2 - Use CTR mode and prefix the IV in the output algstr = "Aes128/CTR" Debug.Print algstr & " + PREFIX" ct = cipherEncryptBytes(pt, key, iv, algstr, PKI_IV_PREFIX) Debug.Print "CT=" & cnvHexStrFromBytes(ct) dt = cipherDecryptBytes(ct, key, iv, algstr, PKI_IV_PREFIX) Debug.Print "dt='" & StrConv(dt, vbUnicode) & "'" ' PART 3 - Use ECB mode and note we use a dummy empty byte array for the IV Dim dummy() As Byte algstr = "Aes128/ECB" Debug.Print algstr ct = cipherEncryptBytes(pt, key, dummy, algstr, 0) Debug.Print "CT=" & cnvHexStrFromBytes(ct) dt = cipherDecryptBytes(ct, key, dummy, algstr, 0) Debug.Print "dt='" & StrConv(dt, vbUnicode) & "'"