Can't get data element encryption to work.

261 views
Skip to first unread message

rb

unread,
Mar 9, 2014, 8:37:15 PM3/9/14
to intersys...@googlegroups.com
Hi

I am working on encrypting a few on my data fields and can't seem to get it working. I have also tried using managed key file with no luck.

The encrypting part seems to work, but the the decrypting.


ERROR in page definition:
ERROR #5002: Cache error: MVFILE.ParcelModel:%OpenModel: <ILLEGAL VALUE>zDecrypt+3^MVFILE.ParcelModel.1


Method %OnLoadModel(pSource As MVFILE.PARCEL) As %Status
{
  *key='2848BB11-7468-4A75-BD92-F8AB1D2BE346'
  *key='C:\InterSystems\Cache\mgr\ysp.key'
  key='1234567890123456'
  ciphertext=pSource->PROPERTYOWNERDL
  plaintext=@ME->Decrypt(ciphertext,key)
  @ME->OwnDL=plaintext
}

Method %OnStoreModel(pSource As MVFILE.PARCEL) As %Status
{
  *key='2848BB11-7468-4A75-BD92-F8AB1D2BE346'
  *key='C:\InterSystems\Cache\mgr\ysp.key'
  key='1234567890123456'

  plaintext=@ME->OwnDL
  ciphertext=@ME->Encrypt(plaintext,key)
  pSource->PROPERTYOWNERDL = ciphertext
}
ClassMethod 
Encrypt(plaintext,key) As %String [ Language = cache ]
{
  Set text=$ZCONVERT(plaintext,"O","UTF8")
  //Set text=$SYSTEM.Encryption.AESCBCManagedKeyEncrypt(text,key)
  Set text=$SYSTEM.Encryption.AESCBCEncrypt(text,key)
  Set ciphertext=$SYSTEM.Encryption.Base64Encode(text)
  quit ciphertext
}
ClassMethod Decrypt(ciphertext,key) As %String [ Language = cache ]
{
  Set text=$SYSTEM.Encryption.Base64Decode(ciphertext)
  //Set text=$SYSTEM.Encryption.AESCBCManagedKeyDecrypt(text)
  Set text=$SYSTEM.Encryption.AESCBCDecrypt(text,key)
  Set plaintext=$ZCONVERT(text,"I","UTF8")
  quit plaintext
}

Here is the class documentation.

classmethod AESCBCEncrypt(plaintext As %String, key As %String, IV As %String) as %String
This method performs AES encryption in Cipher Block Chained (CBC) mode. Use with AESCBCDecrypt. (See Federal Information Processing Standards Publication 197 and NIST Special Publication 200-38A for more information.)

Input parameters:

plaintext - String to be encrypted. This is padded before encryption to the next mutiple of 16 bytes, using reversible block padding. (See Internet Engineering Task Force Request for Comments 2040 and RSA Laboratories Public-Key Cryptography Standards #7 for more information.)

key - Input key material. Key material 16, 24, or 32 characters long (on Unicode systems, with all character values < 256) is used directly. Otherwise, Password-Based Key Derivation Function #2 (PBKDF2) is used with HMAC-SHA-1, no salt, and one iteration to generate an AES key of the next larger valid size (up to 32 bytes). (See RSA Laboratories Public-Key Cryptography Standards #5 for more information.)

IV - Initialization vector (optional). If this argument is present it must be 16 characters long (on Unicode systems, with all character values < 256). If this argument is omitted (or is an empty string), a null initialization vector is used.

Return value: Encrypted ciphertext.

NOTE: To AES-CBC encrypt and Base64 encode Unicode strings that may contain wide characters, UTF-8 encode the string first:

Set text=$ZCONVERT(plaintext,"O","UTF8")
Set text=$SYSTEM.Encryption.AESCBCEncrypt(text,key,IV)
Set ciphertext=$SYSTEM.Encryption.Base64Encode(text)

To decode and decrypt, perform these operations in the reverse order:

Set text=$SYSTEM.Encryption.Base64Decode(ciphertext)
Set text=$SYSTEM.Encryption.AESCBCDecrypt(text,key,IV)
Set plaintext=$ZCONVERT(text,"I","UTF8")

classmethod AESCBCDecrypt(ciphertext As %String, key As %String, IV As %String) as %String
This method performs AES decryption in Cipher Block Chained (CBC) mode. Use with AESCBCEncrypt. (See Federal Information Processing Standards Publication 197 and NIST Special Publication 200-38A for more information.)

Input parameters:

ciphertext - Encrypted ciphertext, as generated by AESCBCEncrypt.

key - Input key material. Key material 16, 24, or 32 characters long (on Unicode systems, with all character values < 256) is used directly. Otherwise, Password-Based Key Derivation Function #2 (PBKDF2) is used with HMAC-SHA-1, no salt, and one iteration to generate an AES key of the next larger valid size (up to 32 bytes). (See RSA Laboratories Public-Key Cryptography Standards #5 for more information.)

IV - Initialization vector (optional). If this argument is present it must be 16 characters long (on Unicode systems, with all character values < 256). If this argument is omitted (or is an empty string), a null initialization vector is used.

Return value: Decrypted original plaintext, with block padding removed.
 

Amir Samary

unread,
Mar 10, 2014, 5:59:59 PM3/10/14
to intersys...@googlegroups.com
Hi!

These are simpler and do both encryption/decryption and the Base64Encode/Decode in just one call:


Set clearText = $System.Encryption.AESBase64Decode(pEncryptedText ,”<password>")

Set encryptedText = $System.Encryption.AESBase64Encode(oClearText,”<password>”)

Kind regards,

Amir Samary - Senior Sales Engineer
InterSystems Chile - www.intersystemschile.cl
Avenida del Valle 890 - 6to piso
Ciudad Empresarial, Santiago - Chile

Simplicity is the ultimate sophistication (da Vinci)
Caché and Ensemble gives you Power through Simplicity (InterSystems)



--
You received this message because you are subscribed to the Google Groups "InterSystems: Zen Community" group.
To post to this group, send email to InterSys...@googlegroups.com
To unsubscribe from this group, send email to InterSystems-Z...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/InterSystems-ZEN?hl=en
Zen Community Terms and Conditions: http://groups.google.com/group/InterSystems-ZEN/web/community-terms-and-conditions
---
You received this message because you are subscribed to the Google Groups "InterSystems: Zen Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to intersystems-z...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

rb

unread,
Mar 11, 2014, 6:09:52 PM3/11/14
to intersys...@googlegroups.com
Hi Amir,

I changed my code to use your simpler routines, but I am still getting the same error.

One note, the encryption is working, just the decode is getting error.

thanks,

Rich

Amir Samary

unread,
Mar 11, 2014, 9:57:07 PM3/11/14
to intersys...@googlegroups.com
Hi!

Well… There are only two options I can think of:

1- The ciphered text is being changed in between calls
2- The password is being changed in between calls

Can you send me the entire controller class and the entity associated with it? What is the definition of property PROPERTYOWNERDL?

Does it have a TRUNCATE=1? That could be truncating the ciphered text, for instance….

Kind regards,

Amir Samary - Senior Sales Engineer
InterSystems Chile - www.intersystemschile.cl
Avenida del Valle 890 - 6to piso
Ciudad Empresarial, Santiago - Chile

Simplicity is the ultimate sophistication (da Vinci)
Caché and Ensemble gives you Power through Simplicity (InterSystems)



rb

unread,
Mar 11, 2014, 11:34:16 PM3/11/14
to intersys...@googlegroups.com
Hi Amir,

here is the model class...

thank you for your assistance.

Class MVFILE.ParcelModel Extends %ZEN.DataModel.ObjectDataModel [ Language = mvbasic, LegacyInstanceContext ]
{

Property ItemId As %String;
Property ResetCounts As %String;
Property OwnFirstName As %String;
Property OwnMiddleName As %String;
Property OwnLastName As %String;
Property OwnFullName As %String;
Property OwnAddress1 As %String;
Property OwnAddress2 As %String;
Property OwnUnitApt As %String;
Property OwnLocation As %String;
Property OwnCity As %String;
Property OwnState As %String;
Property OwnCounty As %String;
Property OwnPostalCode As %String;
Property OwnHomePhone As %String;
Property OwnWorkPhone As %String;
Property OwnCellPhone As %String;
Property OwnEmail As %String;
Property OwnDL As %String;
Property OwnDLState As %String;
Property OwnSSN As %String;
Property EnteredByUser As %String;
Property EnteredBatch As %String;
Property EnteredDate As %String;
Property ActHistLast As %String;
Property ActChangeByUserLast As %String;
Property ActDateLast As %String;
Property Action As %String;

Method %OnOpenSource(pID As %String, pConcurrency As %Integer = -1, Output pSC As %Status) As %RegisteredObject
{
  Return "MVFILE.PARCEL"->%OpenId(pID,pConcurrency,pSC)
}

Method %OnSaveSource(pSource As MVFILE.PARCEL) As %Status
{
  tSC = pSource->%Save()
  if ("%SYSTEM.Status"->IsOK(tSC)) then
    @ME->%id = pSource->%Id()
   end
  Return tSC

}

Method %OnLoadModel(pSource As MVFILE.PARCEL) As %Status
{
  idate=date()

  *key='2848BB11-7468-4A75-BD92-F8AB1D2BE346'
  *key='C:\InterSystems\Cache\mgr\ysp.key'
  key='1234567890123456'
  @ME->ItemId = pSource->ItemId
  @ME->OwnFirstName = pSource->PROPERTYOWNERFIRSTNAME
  @ME->OwnMiddleName = pSource->PROPERTYOWNERMIDDLENAME
  @ME->OwnLastName = pSource->PROPERTYOWNERLASTNAME
  @ME->OwnFullName = pSource->PROPERTYOWNERFULLNAME
  @ME->OwnAddress1 = pSource->PROPERTYOWNERADDRESS1
  @ME->OwnAddress2 = pSource->PROPERTYOWNERADDRESS2
  @ME->OwnUnitApt = pSource->PROPERTYOWNERUNITAPT
  @ME->OwnLocation = pSource->PROPERTYOWNERLOCATION
  @ME->OwnCity = pSource->PROPERTYOWNERCITY
  @ME->OwnState = pSource->PROPERTYOWNERSTATE
  @ME->OwnCounty = pSource->PROPERTYOWNERCOUNTY
  @ME->OwnPostalCode = pSource->PROPERTYOWNERPOSTALCODE
  @ME->OwnHomePhone = pSource->PROPERTYOWNERHOMEPHONE
  @ME->OwnWorkPhone = pSource->PROPERTYOWNERWORKPHONE
  @ME->OwnCellPhone = pSource->PROPERTYOWNERCELLPHONE
  @ME->OwnEmail = pSource->PROPERTYOWNEREMAIL
  ciphertext=pSource->PROPERTYOWNERDL
  plaintext=@ME->Decrypt(ciphertext,key)
  plaintext=''
  @ME->OwnDL=plaintext
  @ME->OwnDLState = pSource->PROPERTYOWNERDLSTATE
  @ME->OwnSSN = pSource->PROPERTYOWNERSSN
  @ME->EnteredByUser = pSource->ENTEREDBYUSER
  @ME->EnteredBatch = pSource->ENTEREDBATCH
  @ME->EnteredDate = oconv(pSource->ENTEREDDATE,'d4/')
  @ME->ActHistLast = pSource->ACTIVITYHISTORYLAST
  @ME->ActChangeByUserLast = pSource->ACTIVITYCHANGEBYUSERLAST
  @ME->ActDateLast = oconv(pSource->ACTIVITYDATELAST,'d4/')
  @ME->ResetCounts='N'
  Return "%SYSTEM.Status"->OK()

}

Method %OnStoreModel(pSource As MVFILE.PARCEL) As %Status
{
  *key='2848BB11-7468-4A75-BD92-F8AB1D2BE346'
  *key='C:\InterSystems\Cache\mgr\ysp.key'
  key='1234567890123456'
  pSource->ItemId = @ME->ItemId
  pSource->PROPERTYOWNERFIRSTNAME = @ME->OwnFirstName
  pSource->PROPERTYOWNERMIDDLENAME = @ME->OwnMiddleName
  pSource->PROPERTYOWNERLASTNAME = @ME->OwnLastName
  pSource->PROPERTYOWNERFULLNAME = @ME->OwnFullName
  pSource->PROPERTYOWNERADDRESS1 = @ME->OwnAddress1
  pSource->PROPERTYOWNERADDRESS2 = @ME->OwnAddress2
  pSource->PROPERTYOWNERUNITAPT = @ME->OwnUnitApt
  pSource->PROPERTYOWNERLOCATION = @ME->OwnLocation
  pSource->PROPERTYOWNERCITY = @ME->OwnCity
  pSource->PROPERTYOWNERSTATE = @ME->OwnState
  pSource->PROPERTYOWNERCOUNTY = @ME->OwnCounty
  pSource->PROPERTYOWNERPOSTALCODE = @ME->OwnPostalCode
  pSource->PROPERTYOWNERHOMEPHONE = @ME->OwnHomePhone
  pSource->PROPERTYOWNERWORKPHONE = @ME->OwnWorkPhone
  pSource->PROPERTYOWNERCELLPHONE = @ME->OwnCellPhone
  pSource->PROPERTYOWNEREMAIL = @ME->OwnEmail

  plaintext=@ME->OwnDL
  ciphertext=@ME->Encrypt(plaintext,key)
  pSource->PROPERTYOWNERDL = ciphertext
  pSource->PROPERTYOWNERDLSTATE = @ME->OwnDLState
  pSource->PROPERTYOWNERSSN = @ME->OwnSSN
  pSource->ENTEREDBYUSER = @ME->EnteredByUser
  pSource->ENTEREDBATCH = @ME->EnteredBatch
  pSource->ENTEREDDATE = iconv(@ME->EnteredDate,'d4/')

  return pSource->%Save()
}

Method Encrypt(plaintext, key) As %String [ Language = cache ]
{
  Set ciphertext = $System.Encryption.AESBase64Encode(plaintext,key)
  //Set text=$ZCONVERT(plaintext,"O","UTF8")
  //Set text=$SYSTEM.Encryption.AESCBCManagedKeyEncrypt(text,key)
  //Set text=$SYSTEM.Encryption.AESCBCEncrypt(text,key)
  //Set ciphertext=$SYSTEM.Encryption.Base64Encode(text)
  quit ciphertext
}

Method Decrypt(ciphertext, key) As %String [ Language = cache ]
{
  Set plaintext = $System.Encryption.AESBase64Decode(ciphertext,key)
  //Set text=$SYSTEM.Encryption.Base64Decode(ciphertext)
  //Set text=$SYSTEM.Encryption.AESCBCManagedKeyDecrypt(text)
  //Set text=$SYSTEM.Encryption.AESCBCDecrypt(text,key)
  //Set plaintext=$ZCONVERT(text,"I","UTF8")
  quit plaintext
}


Method %OnNewSource(Output pSC As %Status) As %RegisteredObject
{
  Return "MVFILE.PARCEL"->%New()
}

}

Amir Samary

unread,
Mar 12, 2014, 8:48:57 AM3/12/14
to intersys...@googlegroups.com
Hi!

Can you post your MVFILE.PARCEL class too? At least the PROPERTYOWNERDL property definition and anything related to it...

There is something weird on your %OnLoadModel though:

ciphertext=pSource->PROPERTYOWNERDL
  plaintext=@ME->Decrypt(ciphertext,key)
  plaintext=''

I am not a MVBASIC expert but it seems you are overwriting plaintext with the empty string just after calling Decrypt…

Please send me your model class too. 

Kind regards,

Amir Samary - Senior Sales Engineer
InterSystems Chile - www.intersystemschile.cl
Avenida del Valle 890 - 6to piso
Ciudad Empresarial, Santiago - Chile

Simplicity is the ultimate sophistication (da Vinci)
Caché and Ensemble gives you Power through Simplicity (InterSystems)



rb

unread,
Mar 12, 2014, 2:29:08 PM3/12/14
to intersys...@googlegroups.com
Yes, you asked for that and I missed the PARCEL class.

You are correct, I set the field to null in some of my testing. Please disregard that line.


Class MVFILE.PARCEL Extends (%Persistent, %MV.Adaptor, %XML.Adaptor) [ ClassType = persistent, Inheritance = right, ProcedureBlock, SqlRowIdPrivate ]
{

Parameter MVAUTOLOCK = 0;

Parameter MVCLEARDICT = 0;

Parameter MVCREATE As BOOLEAN = 0;

Parameter MVFILENAME As STRING = "PARCEL";

Parameter MVREPOPULATE = 0;


Property PROPERTYOWNERDL As %String(COLLATION = "SPACE", MAXLEN = "", MVATTRIBUTE = 20, MVNAME = "PROPERTYOWNERDL", MVPROJECTED = 0, MVTYPE = "D");


Index indexItemId On ItemId [ IdKey, PrimaryKey ];

}
Message has been deleted

rb

unread,
Mar 12, 2014, 11:54:08 PM3/12/14
to intersys...@googlegroups.com
FYI, I get the error message when page is loading, not when method is called.

thanks
Rich

Amir Samary

unread,
Mar 13, 2014, 3:03:33 PM3/13/14
to intersys...@googlegroups.com
Hi!

The error message isn’t attached… Can you attach it?

Kind regards,

Amir Samary - Senior Sales Engineer
InterSystems Chile - www.intersystemschile.cl
Avenida del Valle 890 - 6to piso
Ciudad Empresarial, Santiago - Chile

Simplicity is the ultimate sophistication (da Vinci)
Caché and Ensemble gives you Power through Simplicity (InterSystems)



Amir Samary

unread,
Mar 13, 2014, 3:24:25 PM3/13/14
to intersys...@googlegroups.com
Hi!

I am not an MV expert. In fact, I know nothing about it. But I was looking at the documentation trying to find what could be changing your data in between. I noticed the parameter MVTYPE and that your property is setting it to “D” what, accordingly to the documentation, causes a call to a MVITYPE conversion. Have you checked if this is changing your data? 

I understand you can save the data but not open it back, right? Can you manually encrypt a string say:

Set enc = $System.Encryption.AESBase64Encode(“AAA","1234567890123456")
Write !,enc
WSgGboH0uw609GXy5HHj6w==

And save an object on your class using your UI with the same data (“AAA”) and look at the global to see if what is stored on your global is the same of the output above? The idea is to determine if the data is being corrupted on saving or on loading…

Kind regards,

Amir Samary - Senior Sales Engineer
InterSystems Chile - www.intersystemschile.cl
Avenida del Valle 890 - 6to piso
Ciudad Empresarial, Santiago - Chile

Simplicity is the ultimate sophistication (da Vinci)
Caché and Ensemble gives you Power through Simplicity (InterSystems)



rb

unread,
Mar 13, 2014, 5:24:49 PM3/13/14
to intersys...@googlegroups.com

This is the error at the top of web page. All fields on my form are greyed out. If I remove or comment  the decrypt statement (Set text=$SYSTEM.Encryption.AESCBCDecrypt(text,key,IV)) , the page opens without an error and I am able to encrypt the data.

I will try your suggesting of comparing encrypted data before and after write.


 

rb

unread,
Mar 14, 2014, 5:08:42 PM3/14/14
to intersys...@googlegroups.com
Hi Amir,
 
I was able to get this working with your help and help on mv board.

Here is what works. The decrypt does not like a null or a non-encrypted value.

if plaintext='' then
   ciphertext=''
end else
 try
    ciphertext="%SYSTEM.Encryption"->AESBase64Encode(plaintext,key)
  catch errs
    ciphertext=''
  end try
end


  if ciphertext = '' then
    plaintext=''
  end else
    try
      plaintext="%SYSTEM.Encryption"->AESBase64Decode(ciphertext,key)
    catch errs
      plaintext=''
    end try
  end

thanks again,
Rich
Reply all
Reply to author
Forward
0 new messages