AES cipher block chaining in RPGLE - encryption

I am looking for any clues as to how I can achieve cipher blocking chaining in RPGLE as I wish to encrypt data than is larger than 16 bytes.
My understanding is that this is a necessity for AES to ensure it is split into only 16 byte blocks.
I am using the Qc3EncryptData() API
*******************************************************************
*Data definitions
*******************************************************************
*ALGD0200 algorithm description structure
DQC3D0200 DS
* Qc3 Format ALGD0200
D QC3BCA 1 4B 0
* Block Cipher Alg
D QC3BL 5 8B 0
* Block Length
D QC3MODE 9 9
* Mode
D QC3PO 10 10
* Pad Option
D QC3PC 11 11
* Pad Character
D QC3ERVED 12 12
* Reserved
D QC3MACL 13 16B 0
* MAC Length
D QC3EKS 17 20B 0
* Effective Key Size
D QC3IV 21 52
* Init Vector
*ALGD0300 algorithm description structure
DQC3D0300 DS
* Qc3 Format ALGD0300
D QC3SCA 1 4B 0
* Stream Cipher Alg
*ALGD0400 algorithm description structure
DQC3D0400 DS
* Qc3 Format ALGD0400
D QC3PKA 1 4B 0
* Public Key Alg
D QC3PKABF 5 5
* PKA Block Format
D QC3ERVED00 6 8
* Reserved
D QC3SHA 9 12B 0
* Signing Hash Alg
*ALGD0500 algorithm description structure
DQC3D0500 DS
* Qc3 Format ALGD0500
D QC3HA 1 4B 0
* Hash Alg
*DATA0200 array data format structure
DQC3A0200 DS
* Qc3 Format DATA0200
D QC3DP 1 16*
* Data Ptr
D QC3DL 17 20B 0
* Data Len
D QC3ERVED01 21 32
* Reserved
*KEYD0200 key description format structure
DQC3D020000 DS
* Qc3 Format KEYD0200
D QC3KT 1 4B 0
* Key Type
D QC3KSL 5 8B 0
* Key String Len
D QC3KF 9 9
* Key Format
D QC3ERVED02 10 12 inz(x'000000')
* Reserved
*QC3KS 13 13
*
* 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
*Encrypt Data (OPM, QC3ENCDT; ILE, Qc3EncryptData) API protects
*data privacy by scrambling clear data into an unintelligible form.
*Qc3EncryptData Pr ExtProc('Qc3EncryptData')
D Qc3EncryptData Pr ExtPgm('QC3ENCDT')
D clrDta 100a
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 100a
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.
*Qc3DecryptData Pr ExtProc('Qc3DecryptData')
D Qc3DecryptData Pr ExtPgm('QC3DECDT')
D encryptedData 100a
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 100a
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 100a
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 100a
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* Block cipher algorithm
* 20 DES
* 21 Triple DES
* 22 AES
C Eval QC3BCA = 22
*Block length
* 8 DES
* 8 Triple DES
* 16 AES
C Eval QC3BL = 16
*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 = 22
* Key Format
C Eval QC3KF = '0'
* Key String
C Eval KeyString = pKeyString
* Key Length
C Eval QC3KSL = %len(%trim(KeyString))
C Eval KeyC = QC3D020000 + %trim(KeyString)
C Eval Key = KeyC
* Encrypt
C Select
C When pAction = 'E'
C Eval clrDta = pClrDta
C Eval clrDtaLen = %len(%trim(clrDta))
C Eval EncryptedData = *blanks
C Eval encryptedBufL = %size(encryptedData)
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 Eval pEncDta = EncryptedData
* Decrypt
C When pAction = 'D'
C**** Eval EncryptedData = %Trim(pEncDta)
C Eval EncryptedData = pEncDta
C Eval EncryptedDtaL = %len(%trim(EncryptedData))
c If EncryptedDtaL <> 16
C Eval EncryptedDtaL = 32
C Endif
C Eval clrDta = *blanks
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 Eval pclrDta = ClrDta
C Other
C Eval *InLr = *On
C Endsl
C Return
**********************************************************************

You prototypes aren't the best...
Assuming a recent version of IBM i, you can have a char field of 16M, this is how you'd code a prototype that could handle encrypting up to 16MB of data
D Qc3EncryptData Pr ExtPgm('QC3ENCDT')
D clrDta a len(16733104) options(*varsize) const
D clrDtaLen 10I 0
In your QC3D0200 algorithm description structure, you tell the API whether or not to pad (QC3PO) and what character to pad with (QC3PC).
With the above prototype and the proper settings, you can encrypt data upto 16MB. If you pass for instance 100 bytes, the algorithm will automatically pad to 112 bytes...
You'd need to make sure that you allow for the automatic padding in your encrypted value buffer.

Related

Number of pairs of a and b given w

Given two statements
1) w + a = b
2) a & b = 0 (bitwise and)
Find the number of pairs of a and b given w.
Can someone please help me how should i solve this problem.
There are inifinite number of pairs. Example for w=11bin
w = b - a
1001 b
0110 a
11 w
10001 b
01110 a
11 w
1..k zeros..1
0..k ones...0
11
We can build similar infinite sequence of pairs for the leftmost 1-bit of any given value w

Can't modify the contents of specific columns with binary values

I have 10 columns in the data.table DataDia.
> head(DataDia[,c(7:16)])
Type soin 01 Type soin 02 Type soin 03 Type soin 04 Type soin 05 Type soin 06 Type soin 07 Type soin 08 Type soin 09 Type soin 10
1: crme de jour sérum démaquillant à rincer
2: masque démaquillant à rincer
3: crme de nuit sérum lotion
4: sérum lotion eau florale
5: crme de jour sérum démaquillant sans rinage
6: crme de nuit huile sérum
I just want to apply a general function that modify the contains just only for these columns to binary values. If the columns have empty cells then it will be replaced by 0 else by 1.
So I write these code:
DataDia[,DataDia[,c(5:10)]:=lapply(colnames(DataDia[,c(5:10)]), function(x) {if (DataDia[,x]==""){0} else {1}})]
But I get this error:
Error in [.data.table(DataDia, , :=(DataDia[, c(7:16)],
lapply(colnames(DataDia[, : LHS of := must be a symbol, or an atomic
vector (column names or positions).
Note that I want to work with data.table operations. But I don't know why this doesn't work here?
Thank you in advance!
First, a vocabulary point : your cells with "" are not empty cells, but cells containing an empty character string with is in itself a value. "Empty cells" refer to missing values, which appear as NA in a table.
Usually, missing data should already be identified as such when loading the data in R (e.g. by the na.strings = argument in the read.table function). If you tell me how you loaded your data, I could help you on how to do this.
As for your code, I would go for something much simpler:
DataDia[,5:10] <- data.table(0+ !(DataDia[,5:10] == ""))
NB: The 0 + part is used here to obtain a numric value of 0 for FALSE and 1 for TRUE. The exclamation mark is used to test the contrary of the written condition (we want it to return FALSE or 0 when the cell is ""). You need the data.table function because matrices do not seem to coerce correctly to data.table.
Here is the code working on a sample dataset:
> DataDia
Produit1 Produit2 Produit3 Produit4
1: b c d
2: a b c
3: a c d
4: a b d
5: a c d
6: a b c d
7: b c d
8: a b c d
9: a b d
10: a b c d
> DataDia[,2:3] <- data.table(0+ !(DataDia[,2:3] == ""))
> DataDia
Produit1 Produit2 Produit3 Produit4
1: 1 1 d
2: a 1 1
3: a 0 1 d
4: a 1 0 d
5: a 0 1 d
6: a 1 1 d
7: 1 1 d
8: a 1 1 d
9: a 1 0 d
10: a 1 1 d

Calculating entropy in R

A=c("f","t","t","f","t","f","f","f","t","f")
B=c("t","t","t","t","t","f","f","f","t","t")
class=c("+","+","+","-","+","-","-","-","-","-")
df=data.frame(A,B,class)
df
A B class
1 f t +
2 t t +
3 t t +
4 f t -
5 t t +
6 f f -
7 f f -
8 f f -
9 t t -
10 f t -
I partitioned attribute A or B due to the class as follows :
{A}
[T , F]
/ \
------- -------
[3+,1-] [1+,5-]
{B}
[T , F]
/ \
------- -------
[4+,3-] [0+,3-]
depending on the above formula I calculated entropy by this code in R .
1- for attribute A
t=table(A,class)
t
class
A - +
f 5 1
t 1 3
prop1=t[1,]/sum(t[1,])
prop1
- +
0.8333333 0.1666667
prop2=t[2,]/sum(t[2,])
prop2
- +
0.25 0.75
H1=-(prop1[1]*log2(prop1[1]))-(prop1[2]*log2(prop1[2]))
H1
0.6500224
H2=-(prop2[1]*log2(prop2[1]))-(prop2[2]*log2(prop2[2]))
H2
0.8112781
entropy=(table(A)[1]/length(A))*H1 +(table(A)[2]/length(A))*H2
entropy
0.7145247
2- for attribute B
t=table(B,class)
t
class
B - +
f 3 0
t 3 4
prop1=t[1,]/sum(t[1,])
prop1
- +
1 0
prop2=t[2,]/sum(t[2,])
prop2
- +
0.4285714 0.5714286
H1=-(prop1[1]*log2(prop1[1]))-(prop1[2]*log2(prop1[2]))
H1
NaN
H2=-(prop2[1]*log2(prop2[1]))-(prop2[2]*log2(prop2[2]))
H2
0.9852281
entropy=(table(B)[1]/length(B))*H1 +(table(B)[2]/length(B))*H2
entropy
NaN
when I calculate entropy for attribute B the result give me NaN that is due to zero(0) (log2(0) is error ) . in such situation how can I fix this error or how can make H1 give me zero instead of NaN

How create an Rcpp NumericVector with more than 20 entries?

Creating a NumericVector with more than 20 elements leads to error messages.
This is in agreement with this document (at the very bottom): http://statr.me/rcpp-note/api/Vector_funs.html
Currently, I expose a class (using RCPP_MODULE) of which one of its methods returns the desired NumericVector. How can I return more than 20 elements?
#include <Rcpp.h>
class nvt {
public:
nvt(int x, double y) {...}
NumericVector run(void) {
....
return NumericVector::create(_["a"]=1,_["b"]=2, .....,_["c"]=21);
}
};
RCPP_MODULE(nvt_module){
class_<nvt>("nvt")
.constructor<int,double>("some description")
.method("run", &nvt::run,"some description")
;
}
Create the vector with the size you need then assign the values & names. This is an Rcpp "inline" function (easier for folks to try it out) but it'll work in your context:
library(Rcpp)
library(inline)
big_vec <- rcpp(body="
NumericVector run(26);
CharacterVector run_names(26);
# make up some data
for (int i=0; i<26; i++) { run[i] = i+1; };
# make up some names
for (int i=0; i<26; i++) { run_names[i] = std::string(1, (char)('A'+i)); };
run.names() = run_names;
return(run);
")
big_vec()
## A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
Bob already showed you that a) you mistakenly took the constraint on the macro-defined create() helper to be binding, and b) how to do this via the inline package and loops.
Here is an alternate solution using Rcpp Attribute. Copy the following to a file, say, /tmp/named.cpp:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector makevec(CharacterVector nm) {
NumericVector v(nm.size());
v = Range(1, nm.size());
v.attr("names") = nm;
return v;
}
/*** R
makevec(LETTERS)
makevec(letters[1:10])
*/
Simply calling sourceCpp("/tmp/named.cpp") will compile, link, load and also execute the R illustration at the bottom:
R> sourceCpp("/tmp/named.cpp")
R> makevec(LETTERS)
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
R> makevec(letters[1:10])
a b c d e f g h i j
1 2 3 4 5 6 7 8 9 10
R>

How to create new column based on another column's contents in R

This is a sample of my data set:
>data
C1 C2 C3 C4 C5 C6
ATOM 1 -4.794 -7.29 6.756 C
ATOM 1 -4.357 -6.181 6.473 O
ATOM 2 -5.878 -8.511 5.233 C
ATOM 2 -7.02 -9.179 5.732 C
ATOM 3 -7.479 -9.499 6.108 C
ATOM 5 -4.873 -7.021 6.767 C
ATOM 8 -3.891 -6.723 6.31 O
ATOM 1 -7.515 -10.402 -0.621 C
ATOM 1 -7.26 -11.716 -0.22 O
ATOM 2 -7.53 -10.348 0.581 C
ATOM 3 -6.689 -11.008 2.344 C
Ultimately, What I want to achieve is to have a new column that detects when the numbers in C2 reset back to 1, as shown below:
>data
C1 C2 C3 C4 C5 C6 C7
ATOM 1 -4.794 -7.29 6.756 C 1
ATOM 1 -4.357 -6.181 6.473 O 1
ATOM 2 -5.878 -8.511 5.233 C 1
ATOM 2 -7.02 -9.179 5.732 C 1
ATOM 3 -7.479 -9.499 6.108 C 1
ATOM 5 -4.873 -7.021 6.767 C 1
ATOM 8 -3.891 -6.723 6.31 O 1
ATOM 1 -7.515 -10.402 -0.621 C 2
ATOM 1 -7.26 -11.716 -0.22 O 2
ATOM 2 -7.53 -10.348 0.581 C 2
ATOM 3 -6.689 -11.008 2.344 C 2
I used a for loop with a nested if statement. My method was to compare an existing row with the following row. if the value is less than/ equal to the existing value, I assign 1 to the new column - if not, I increment the old count by 1.
C7 = NULL
i <- 1
index <- 1
for ( i in 1:nrow(data)){
if(data$C2[i] <= data$C2[i+1]){
data$C7 = index
} else {
data$C7 <- index + 1
}
}
**This code doesnt work and this error occurs
Error in if (data$C2[i] <= data$C2[i + 1]) { :
missing value where TRUE/FALSE needed **
I'm not quite sure what I'm doing wrong and have a feeling that there's an even better way to do this. I appreciate any help -- thank you in advance!
You don't need a loop:
data$C7 <- c(1, cumsum(diff(data$C2) < 0) + 1)
C1 C2 C3 C4 C5 C6 C7
1 ATOM 1 -4.794 -7.290 6.756 C 1
2 ATOM 1 -4.357 -6.181 6.473 O 1
3 ATOM 2 -5.878 -8.511 5.233 C 1
4 ATOM 2 -7.020 -9.179 5.732 C 1
5 ATOM 3 -7.479 -9.499 6.108 C 1
6 ATOM 5 -4.873 -7.021 6.767 C 1
7 ATOM 8 -3.891 -6.723 6.310 O 1
8 ATOM 1 -7.515 -10.402 -0.621 C 2
9 ATOM 1 -7.260 -11.716 -0.220 O 2
10 ATOM 2 -7.530 -10.348 0.581 C 2
11 ATOM 3 -6.689 -11.008 2.344 C 2

Resources