Monday, May 04, 2009

Base64 Encoding with Pluggable Encryption

I dedicate this post to Chris Heller since he is the person that pointed me at PeopleSoft's pluggable encryption in his comments to my last post on Base64 Encoding for PeopleSoft. I had not considered PeopleSoft's pluggable encryption for base64 encoding. Thanks Chris!

Before we can base64 encode strings with PeopleSoft's Pluggable Encryption, we need to create an Algorithm Chain and an Encryption Profile. PeopleBooks does an excellent job of explaining each of these terms as well as telling how to create each of these components. Since PeopleSoft delivers the base64 encryption algorithm with the PSPETSSL encryption library, we can move right into defining the Algorithm Chain. To define the chain, navigate to PeopleTools > Security > Encryption > Algorithm Chain. Add the new value BASE64_ENCODE and add the following Algorithms in order:

  1. PSUnicodeToAscii
  2. base64_encode
  3. PSAsciiToUnicode

Be sure to set the sequence number for each row (1-3). Save and navigate to PeopleTools > Security > Encryption > Encryption Profile. Add the new value BASE64_ENCODE. Specify the algorithm chain BASE64_ENCODE and save. We can now test this pluggable encryption profile with a little PeopleCode:

Local object &crypto = CreateObject("Crypt");
&crypto.Open("BASE64_ENCODE");
&crypto.UpdateData("Hello World");
MessageBox(0, "", 0, 0, "Encrypted: " | &crypto.Result);

And, the result should be: SGVsbG8gV29ybGQ=. I am sure you will all agree that this solution is much simpler than the ugly Java Reflection I previously demonstrated. Furthermore, this method is well documented in PeopleBooks and supported by PeopleSoft.

If I am reading PeopleBooks right, Pluggable Encryption only works with ASCII text. That is why we have to use the PSUnicodeToAscii and PSAsciiToUnicode algorithms in our algorithm chain. What this means is that we still need to use an alternative for base64 encoding binary data, a requirement when embedding binary data in XML documents.

40 comments:

Ciphersbak said...

Hi Jim,

This is really helpful..
Thanks a lot for sharing

Cheers!
Prashant

mymithraa said...

Jim,

Whether Byte Array and Base64 Encoding are same??

Thanks,

Jim Marion said...

@mymithraa, a Byte Array is an unencoded series of bytes stored in an array. Base64 is an encoded form. Base64 converts binary characters into text characters. They are not the same thing. Base64 data can always be represented in text form. A byte array can only be presented in text form if the bytes represent character data.

PE said...

Jim,
I tried this and am getting a internal error when I call the open method on the crypt object.

I am on PT849.

What could be the cause ?

Jim Marion said...

@PE, you may want to open a case with Oracle Support. I do not receive errors.

Stan the Man said...

HI Jim,
Using your example, how would one go about decrypting the ecncrypted "hello world" string?
Thanks
Stan

Jim Marion said...

@Stanton, you are taking me back a few months... Thank you for letting me know that you find this information useful.

There is an algorithm id named base64_decode. I don't have my algorithm chain in front of me, but I believe you follow the same steps as above, replacing each instance of encode with decode. So, the algorithm chain/encryption profile (depends on tools version) would be named BASE64_DECODE and step 2 in the chain will use base64_decode. The 3DES CBC B64 DECRYPT chain described in PeopleBooks Securing Data with Pluggable Cryptography shows the exact steps (just remove the 3des_ks168_cbc_decrypt step).

Ganesh said...

Hi Jim,

I had another question,

How can I encrypt the clear text password entered by user and then compare the value with enrypted password stored in the userprofile table ?

I don't want to decrpt.

Jim Marion said...

@Ganesh, are you referring to web services as you were in your prior question? Unfortunately, I don't have an answer for you. As you probably know, the encrypted password is stored in PSOPRDEFN. You can check pscipher. If it gives you the same result, then that is your answer.

If you are referring to WS-Security and CI based web services, however, you will want to stick with delivered options. PeopleBooks says that it supports encrypted UsernameTokens. You can also use SAML tokens.

I'm not an expert in PeopleSoft web services or WS security, so I'm not the best person to answer this question. I suggest you post your question on the OTN forum or create a case with Oracle support. OTN forum may give you an answer. Oracle support will definitely give you an answer.

Hari said...

Hi Jim,

We need to encrypt the user password at third party application and then we are going to invoke the PeopleSoft login URL using https connection (same as your PSTOKEN switch user example). At this situation will PeopleSoft accepts the encrypted pwd?

If we need to decrypt the password means will PeopleSoft accept the decrypted password?

Will it invoke the series of sign on PeopleCode? (Which is used to executed when user logs into PeopleSoft)

Thanks for sharing your valuable experience with us.

Jim Marion said...

@Hari, if you post a username and password to the ?cmd=login URL as it sounds like you are planning to do, then you will need to provide the password in the same manner as a user entering a password online. A user would not enter an encrypted password.

If you are using SSL, then the entire stream is encrypted, so you don't have to worry about plain text passwords at that point.

Yes, if you post to the signon URL, then the session will run all the signon PeopleCode.

If you are using signon PeopleCode, then you can actually create your own trusted authentication between the other third party app and PeopleSoft. You can have the third party app send whatever token you want and then have Signon PeopleCode make a call back into that system to validate the token.

Viswanathareddy K said...

Hi Jim,

Is there any back process for the same i mean can we do decryption in same way.

for example we received file information in base64 encrypted format from third party webservice how to get the original file back in peoplesoft.

can we do it as mentioned above in reverse way?

And sorry for lot of doubts.

Viswa.

Jim Marion said...

@Viswa, yes, you can do the reverse of above, but from your comments on other posts, it seems appears that you are dealing with binary data. The process on this particular post only works with base64 encoded text, not binary.

PSSP said...

Hi Jim,
Though this is a old post, I'm commenting here its relevant to my question. I was studying through the PET framework specifically the pkcs7_encrypted_encrypt algorithm. It accepts 2 parameters of which one expects a symmetric algorithm. Now, using the encyrption profile, I couldn't find a way to provide parameters to the symmetric algorithm. Also, the openssl.cnf file is not shipped with the PS s/w. And without this, the Load Library removes the pkcs7 algorithms. Any ideas?

Jim Marion said...

@PSSP, those are some very good questions. Unfortunately, I don't have answers. My recommendation is to post them on the OTN forum.

Raj said...

I am trying to use the HMAC hashing and want to use the hmac_sha1_generate algorithm. Is there an exmple of the algorithm chain for this? I need to use a static key provided by the vendor.

Jim Marion said...

@Raj, I have not seen one for that. You may want to post your question in the PeopleSoft General OTN Forum.

Raj said...

Hi Jim,
Can you help me with the correct way to for the following objects?
CreateJavaObject("javax.crypto.spec");
CreateJavaObject("javax.crypto.Mac");

Thanks
Raj

Jim Marion said...

@Raj, those are Java packages. You can't create an object from a package. You create an object from a class definition. For example, CreateJavaObject("javax.crypto.spec.SecretKeySpec", blah, blah...) where blah, blah... is the constructor parameters.

I am not familiar enough with the javax.crypto.spec and mac packages to create a valuable example for you.

Raj said...

Got it. I will post an example when I am done.
Thanks
Raj

Unknown said...

Hi Jim,

To Create a PasswordDigest for Soap Username token. the norm is BASE64 (SHA-1 (NONCE + CREATION + PASSWORD)) . Can we achieve this using peopletools .. if so whats the chain for this

Jim Marion said...

@Praveen, good question. I have not tried to create that chain before. This PeopleBook contains all of the algorithms and predefined chains. I usually put together a profile and test it using the PeopleCode shown here. You might also want to post this question on the PeopleSoft General Discussion OTN Forum

Vish..... said...

Hi Jim,

My requirement is to encrypt the file using PGP encryption before we send the file to the third party. Its a fixed length format file.

We are working on procuring the PGP SDK and setting up the requisites in Peoplesoft. My question is that do we have to encrypt each column data using UpdateData method before we push the data to a file or we can generate the file and encrypt the complete contents of the file in one go. Will encryption remove wide spaces?

This is the first time I am working on encryption so I am a total naive in this.

Thanks,
KV

Jim Marion said...

@KV, I have not worked with PGP. PeopleBooks seemed to contain conflicting information. In one place it said you have to obtain a license, but it is already installed. In another place, it sounded like you had to obtain a license AND install it.

Pluggable Encryption encrypts whatever you give to it. If you generate the contents of a file in memory in one large string, then it will encrypt the whole thing at once. With this approach, you will have to be careful of memory (file size). You could encrypt each value, but that isn't typically how a file is encrypted. Usually you encrypt the whole file.

If you are generating a file, it may be easier to use the encryption facilities of your operating system (Unix/Linux) to encrypt a file.

Bijay Bhushan Singh said...

hi jim,
i am trying to apply encryption on soap message.for that i just used interop jks peoplesoft keystore. i am using soapui tool to test the web service.in soap request i am able to encrypt the data and i am getting proper data in response but the problem is i am getting response in normal formate not encrypted.so can u pls suggest me did i set anywhere like response also come in encrypted on service operation level i selected encrypted anything else i have to do pls suggest.

Jim Marion said...

@Bijay, I would have expected the request and response to e encrypted. I assume you configured the service operation to be encrypted? You may want to post your question on the PeopleSoft General OTN forum and/or create a global support case just to make sure you have the configuration correct.

Bijay Bhushan Singh said...

@jim,
thanks for ur reply.

Unknown said...

Hi Jim - can we use crypt on an gzip file and transmit it on a web service? If this is possible does it significantly reduces the payload size?

Also, how does the third party system (non-PS) read the Base64 code?

Thanks,
Al

Jim Marion said...

@Al, there is a lot of new stuff with MTOM and files/attachments in web services. I'm not going to comment on that part here. Some IB targets support gizp so the target will gzip the content before it transmits the content (for example over https).

About the non-ps system reading b64, of course the non-ps system would have to expect b64 or it wouldn't read it. B64 is a pretty well known mechanism for transferring binary data, so as long as the target accepts b64, all will be good.

savvy said...

Hi Jim,
I have a requirement where a PS user is entering his credentials through 3rd party App to login into PS system. I don't want that 3rd party is able to peep into the credentials. How can encrypt the password at login and decrypt at PS end?
Communication between two systems is through xml. I want to send the credentials through xml in an encrypted format.

Jim Marion said...

@savvy, you might want to ask this question on the PeopleSoft General Discussion OTN forum

Unknown said...

Hello Jim,

At my client I have to post three outbound files to a sftp server, all are xls format generated using AE. I have to encrypt them using 3DES.

Is there a way for xls file to achieve this? I had trouble open en read each line in my code for encryption.

I did something similar with csv files and was actually quite easy to manage.

Any help is appreciated.

Best regards,
Sam

Jim Marion said...

@Unknown, the key difference is that CSV is text versus XLS(X), which is binary. PeopleCode can't work with binary directly. Instead, you have to convert it to text or use something like Java. Later versions of PeopleCode's File object include File.GetBase64StringFromBinary, which will give you a base64 of an xls(x), but I don't think that is what you want. Instead, I think you will have to rely on Java to create a 3des encrypted file. Then you can then use the file attachment api to move the file to the sftp server. Alternatively, you can use command line utilities to 3des encrypt a file. I don't like this method because it is looser coupled, and can be flakey, but it is often easier to implement. I would go the Java method first, but I wouldn't rule out the command line. If you go the command line route, I would use the Java API to launch the commands, not the exec method. You can find examples in my blog post about controlling stdin and stdout.

Unknown said...

Hello Jim,

Thanks a lot for the quick response. I will focus on Java and lfingers crossed.

Kind regards

Phil said...

Jim,
This post has been very helpful - thanks. In my case, the decoded results are being truncated at 60 characters. It is happening in my Peoplecode and if I use the Test Encryption Profile. Any way around this?

Jim Marion said...

@Phil, interesting. I haven't tried using longer strings, and 60 isn't very long. I have posted several other options for base64. I would suggest using one of those. The database approach may have a size limitation as well, so the PeopleCode/Java version (using Java from PeopleCode) may be your safest route.

Nagesh said...

Hi Jim,

I am able to generate the &crypto.Result but I am not able to use this result. When i am trying to assign this result to any variable and getting null value. I just want to know how to use the &crypto.Result to pass as a value in the headers.

Thanks,
Nagesh

dan said...

Hi Jim, this is a interesting post, I have a question hoping you can answer.

Using the above method I am having to create a Local object for each field I am wanting to encrypt, for example, is this the correct way of doing it?

also can you explain the advantages of your method appose to using the standard peoplecode encrypt and decrypt function?

many thanks


Local object &crypto = CreateObject("Crypt");
&crypto.Open("TRIPLE DES ENC B64");
&crypto.UpdateData(&LAST_NAME);
&LAST_NAME = &crypto.Result;

Local object &crypto9 = CreateObject("Crypt");
&crypto9.Open("TRIPLE DES ENC B64");
&crypto9.UpdateData(&FORE_NAME);
&FORE_NAME = &crypto9.Result;

Local object &crypto1 = CreateObject("Crypt");
&crypto1.Open("TRIPLE DES ENC B64");
&crypto1.UpdateData(&NATIONAL_ID);
&NATIONAL_ID = &crypto1.Result;

Local object &crypto2 = CreateObject("Crypt");
&crypto2.Open("TRIPLE DES ENC B64");
&crypto2.UpdateData(&NAME);
&NAME = &crypto2.Result;

Local object &crypto3 = CreateObject("Crypt");
&crypto3.Open("TRIPLE DES ENC B64");
&crypto3.UpdateData(&address);
&address = &crypto3.Result;

Bob Richley said...

Hi, Jim. We've met a few times at Quest conferences. I also took one of your fluid classes. At the Reconnect Deep Dive, I posed a question about PET. My requirement was to encrypt bank account numbers being sent to ServiceNow via a REST service and also decrypt bank accounts being set from ServiceNow to PeopleSoft. Both ServiceNow and PeopleSoft are in house, so we had full control over the encryption code on both sides. ServiceNow uses JavaScript to encrypt and Decrypt. We decided to use CryptoJS. https://cryptojs.gitbook.io/docs/. We used AEW 123 bit CDC. In PET I setup PSUnicodeToAscii,
aes_ks128_cbc_encrypt,
base64_encode,
PSAsciiToUnicode
Algorithm Chain. I could decrypt using PET, but I couldn't get JavaScript CryptoJS to decrypt. I opened an SR with Oracle and was told PET could decrypt PET only which didn't seem right. Even Greg Kelly didn't think that was right. He thinks a 3rd party should be able to decrypt what PET encrypted. Eventually I opted to write C# to encrypt/decrypt. JavaScritp CryptoJS could decrypt what C# encrypted and vise versa. I would like to get PET to work. Someone at the Deep Dive conference suggested the Algorithm Chain PSUnicodeToAscii
aes_ks256_ecb_encrypt
base64_encode
PSAsciiToUnicode
I couldn't get that to work either. I tried this online tool https://www.devglan.com/online-tools/aes-encryption-decryption and it would not decrypt what PS encrypted. It gets the error
Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
The PS key must be hex and it seems to require prepending with 0x0 and appending with 0x. I generated a key and converted to hex online.
A code snippet for the JavaScript CryptoJS to decrypt AES CBC is
var decrypted = CryptoJS.AES.decrypt({"ciphertext":words}, keyValue, {
iv: ivCodeWords,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
Similarly for ECB
var decrypted = CryptoJS.AES.decrypt({"ciphertext":words}, keyValue, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
The C# snippet is
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
// Get the initialization vector from the encrypted stream
aesAlg.IV = ReadByteArray(msDecrypt);
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))

// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}

}

Any thoughts or suggestions?

Thanks,

Bob

Jim Marion said...

Hi Bob, I have done two-way in PET with HMAC HSA-256. You are correct that the key must begin with 0x. But I don't remember ending with 0x or using 0x0 at the beginning. Just 0x. And yes, it had to be hex.