Skip to main content

Hi,

I have the following code that encrypts and then i can un-encrypt this file, which works file with text files i.e. readable characters.

However if i try to do this with a stored printed data file that contains unreadable characters it produces garbage.

Is there any way to do this using this .NET class?

method-id "EncryptFile" public static.
01 ls-fsInput type "System.IO.FileStream".
01 ls-fsEncrypted type "System.IO.FileStream".
01 ls-des type "System.Security.Cryptography.DESCryptoServiceProvider".
01 ls-desencrypt type "System.Security.Cryptography.ICryptoTransform".
01 ls-cryptostream type "System.Security.Cryptography.CryptoStream".
01 ls-bytearrayinput type "System.Byte" occurs any.
01 ls-len binary-long.
01 ls-ToBase64Transform type "System.Security.Cryptography.ToBase64Transform".
procedure division using by value lnk-inputfile as string
lnk-Outputfile as string
lnk-key as string.

set ls-fsInput to type "System.IO.FileStream"::"New"(lnk-inputfile , type "System.IO.FileMode"::"Open" , type "System.IO.FileAccess"::"Read")
set ls-fsEncrypted to type "System.IO.FileStream"::"New"(lnk-Outputfile , type "System.IO.FileMode"::"Create" , type "System.IO.FileAccess"::"Write")

set ls-des to type "System.Security.Cryptography.DESCryptoServiceProvider"::"New"()
*
* *> Set secret key for DES algorithm.
* *> A 64-bit key and an IV are required for this provider.
*>set ls-DES::"Key" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"Key" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)
*
* *> Set the initialization vector.
*>set ls-DES::"IV" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"IV" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)
*
* *> Create the DES encryptor from this instance.
set ls-desencrypt to ls-DES::"CreateEncryptor"()
*
* *> Create the crypto stream that transforms the file stream by using DES encryption.
set ls-cryptostream to type "System.Security.Cryptography.CryptoStream"::"New"(ls-fsEncrypted , ls-desencrypt , type "System.Security.Cryptography.CryptoStreamMode"::"Write")
*
* *> Read the file text to the byte array.
compute ls-len = ls-fsInput::"Length"
set size of ls-bytearrayinput to ls-len
invoke ls-fsInput::"Read"(ls-bytearrayinput , 0 , ls-bytearrayinput::"Length")
* *> Write out the DES encrypted file.
invoke ls-cryptostream::"Write"(ls-bytearrayinput , 0 , ls-bytearrayinput::"Length")
invoke ls-cryptostream::"Close"()

goback.
end method "EncryptFile".

method-id "DecryptFile" public static.
01 ls-fsRead type "System.IO.FileStream".
01 ls-fsdecrypted type "System.IO.StreamWriter".
01 ls-desdecrypt type "System.Security.Cryptography.ICryptoTransform".
01 ls-des type "System.Security.Cryptography.DESCryptoServiceProvider".
01 ls-cryptostream type "System.Security.Cryptography.CryptoStream".
01 ls-bytearrayinput type "System.Byte" occurs any.
01 ls-len binary-long.
procedure division using by value lnk-inputfile as string
lnk-Outputfile as string
lnk-key as string.

set ls-fsRead to type "System.IO.FileStream"::"New"(lnk-inputfile , type "System.IO.FileMode"::"Open" , type "System.IO.FileAccess"::"Read")

set ls-des to type "System.Security.Cryptography.DESCryptoServiceProvider"::"New"()
*> Set secret key for DES algorithm.
*> A 64-bit key and an IV are required for this provider.
*>set ls-DES::"Key" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"Key" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)

*> Set the initialization vector.
*>set ls-DES::"IV" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"IV" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)

*> Create the DES decryptor from the DES instance.
set ls-desdecrypt to ls-des::"CreateDecryptor"()

*> Create the crypto stream set to read and to do a DES decryption transform on incoming bytes.

set ls-cryptostream to type "System.Security.Cryptography.CryptoStream"::"New"(ls-fsRead , ls-desdecrypt , type "System.Security.Cryptography.CryptoStreamMode"::"Read")

*> Print out the contents of the decrypted file.
set ls-fsDecrypted to type "System.IO.StreamWriter"::"New"(lnk-OutputFile)
invoke ls-fsDecrypted::"Write"(type "System.IO.StreamReader"::"New"(ls-cryptostream)::"ReadToEnd")
invoke ls-fsDecrypted::"Flush"()
invoke ls-fsDecrypted::"Close"()

goback.
end method "DecryptFile".

Hi,

I have the following code that encrypts and then i can un-encrypt this file, which works file with text files i.e. readable characters.

However if i try to do this with a stored printed data file that contains unreadable characters it produces garbage.

Is there any way to do this using this .NET class?

method-id "EncryptFile" public static.
01 ls-fsInput type "System.IO.FileStream".
01 ls-fsEncrypted type "System.IO.FileStream".
01 ls-des type "System.Security.Cryptography.DESCryptoServiceProvider".
01 ls-desencrypt type "System.Security.Cryptography.ICryptoTransform".
01 ls-cryptostream type "System.Security.Cryptography.CryptoStream".
01 ls-bytearrayinput type "System.Byte" occurs any.
01 ls-len binary-long.
01 ls-ToBase64Transform type "System.Security.Cryptography.ToBase64Transform".
procedure division using by value lnk-inputfile as string
lnk-Outputfile as string
lnk-key as string.

set ls-fsInput to type "System.IO.FileStream"::"New"(lnk-inputfile , type "System.IO.FileMode"::"Open" , type "System.IO.FileAccess"::"Read")
set ls-fsEncrypted to type "System.IO.FileStream"::"New"(lnk-Outputfile , type "System.IO.FileMode"::"Create" , type "System.IO.FileAccess"::"Write")

set ls-des to type "System.Security.Cryptography.DESCryptoServiceProvider"::"New"()
*
* *> Set secret key for DES algorithm.
* *> A 64-bit key and an IV are required for this provider.
*>set ls-DES::"Key" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"Key" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)
*
* *> Set the initialization vector.
*>set ls-DES::"IV" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"IV" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)
*
* *> Create the DES encryptor from this instance.
set ls-desencrypt to ls-DES::"CreateEncryptor"()
*
* *> Create the crypto stream that transforms the file stream by using DES encryption.
set ls-cryptostream to type "System.Security.Cryptography.CryptoStream"::"New"(ls-fsEncrypted , ls-desencrypt , type "System.Security.Cryptography.CryptoStreamMode"::"Write")
*
* *> Read the file text to the byte array.
compute ls-len = ls-fsInput::"Length"
set size of ls-bytearrayinput to ls-len
invoke ls-fsInput::"Read"(ls-bytearrayinput , 0 , ls-bytearrayinput::"Length")
* *> Write out the DES encrypted file.
invoke ls-cryptostream::"Write"(ls-bytearrayinput , 0 , ls-bytearrayinput::"Length")
invoke ls-cryptostream::"Close"()

goback.
end method "EncryptFile".

method-id "DecryptFile" public static.
01 ls-fsRead type "System.IO.FileStream".
01 ls-fsdecrypted type "System.IO.StreamWriter".
01 ls-desdecrypt type "System.Security.Cryptography.ICryptoTransform".
01 ls-des type "System.Security.Cryptography.DESCryptoServiceProvider".
01 ls-cryptostream type "System.Security.Cryptography.CryptoStream".
01 ls-bytearrayinput type "System.Byte" occurs any.
01 ls-len binary-long.
procedure division using by value lnk-inputfile as string
lnk-Outputfile as string
lnk-key as string.

set ls-fsRead to type "System.IO.FileStream"::"New"(lnk-inputfile , type "System.IO.FileMode"::"Open" , type "System.IO.FileAccess"::"Read")

set ls-des to type "System.Security.Cryptography.DESCryptoServiceProvider"::"New"()
*> Set secret key for DES algorithm.
*> A 64-bit key and an IV are required for this provider.
*>set ls-DES::"Key" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"Key" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)

*> Set the initialization vector.
*>set ls-DES::"IV" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"IV" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)

*> Create the DES decryptor from the DES instance.
set ls-desdecrypt to ls-des::"CreateDecryptor"()

*> Create the crypto stream set to read and to do a DES decryption transform on incoming bytes.

set ls-cryptostream to type "System.Security.Cryptography.CryptoStream"::"New"(ls-fsRead , ls-desdecrypt , type "System.Security.Cryptography.CryptoStreamMode"::"Read")

*> Print out the contents of the decrypted file.
set ls-fsDecrypted to type "System.IO.StreamWriter"::"New"(lnk-OutputFile)
invoke ls-fsDecrypted::"Write"(type "System.IO.StreamReader"::"New"(ls-cryptostream)::"ReadToEnd")
invoke ls-fsDecrypted::"Flush"()
invoke ls-fsDecrypted::"Close"()

goback.
end method "DecryptFile".

I'm not immediately seeing the problem. I'll have to take a closer look.

Unless you're using a very old version of COBOL for .NET, you don't need quotes around type and method names. That would make your source code easier to read.


Hi,

I have the following code that encrypts and then i can un-encrypt this file, which works file with text files i.e. readable characters.

However if i try to do this with a stored printed data file that contains unreadable characters it produces garbage.

Is there any way to do this using this .NET class?

method-id "EncryptFile" public static.
01 ls-fsInput type "System.IO.FileStream".
01 ls-fsEncrypted type "System.IO.FileStream".
01 ls-des type "System.Security.Cryptography.DESCryptoServiceProvider".
01 ls-desencrypt type "System.Security.Cryptography.ICryptoTransform".
01 ls-cryptostream type "System.Security.Cryptography.CryptoStream".
01 ls-bytearrayinput type "System.Byte" occurs any.
01 ls-len binary-long.
01 ls-ToBase64Transform type "System.Security.Cryptography.ToBase64Transform".
procedure division using by value lnk-inputfile as string
lnk-Outputfile as string
lnk-key as string.

set ls-fsInput to type "System.IO.FileStream"::"New"(lnk-inputfile , type "System.IO.FileMode"::"Open" , type "System.IO.FileAccess"::"Read")
set ls-fsEncrypted to type "System.IO.FileStream"::"New"(lnk-Outputfile , type "System.IO.FileMode"::"Create" , type "System.IO.FileAccess"::"Write")

set ls-des to type "System.Security.Cryptography.DESCryptoServiceProvider"::"New"()
*
* *> Set secret key for DES algorithm.
* *> A 64-bit key and an IV are required for this provider.
*>set ls-DES::"Key" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"Key" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)
*
* *> Set the initialization vector.
*>set ls-DES::"IV" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"IV" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)
*
* *> Create the DES encryptor from this instance.
set ls-desencrypt to ls-DES::"CreateEncryptor"()
*
* *> Create the crypto stream that transforms the file stream by using DES encryption.
set ls-cryptostream to type "System.Security.Cryptography.CryptoStream"::"New"(ls-fsEncrypted , ls-desencrypt , type "System.Security.Cryptography.CryptoStreamMode"::"Write")
*
* *> Read the file text to the byte array.
compute ls-len = ls-fsInput::"Length"
set size of ls-bytearrayinput to ls-len
invoke ls-fsInput::"Read"(ls-bytearrayinput , 0 , ls-bytearrayinput::"Length")
* *> Write out the DES encrypted file.
invoke ls-cryptostream::"Write"(ls-bytearrayinput , 0 , ls-bytearrayinput::"Length")
invoke ls-cryptostream::"Close"()

goback.
end method "EncryptFile".

method-id "DecryptFile" public static.
01 ls-fsRead type "System.IO.FileStream".
01 ls-fsdecrypted type "System.IO.StreamWriter".
01 ls-desdecrypt type "System.Security.Cryptography.ICryptoTransform".
01 ls-des type "System.Security.Cryptography.DESCryptoServiceProvider".
01 ls-cryptostream type "System.Security.Cryptography.CryptoStream".
01 ls-bytearrayinput type "System.Byte" occurs any.
01 ls-len binary-long.
procedure division using by value lnk-inputfile as string
lnk-Outputfile as string
lnk-key as string.

set ls-fsRead to type "System.IO.FileStream"::"New"(lnk-inputfile , type "System.IO.FileMode"::"Open" , type "System.IO.FileAccess"::"Read")

set ls-des to type "System.Security.Cryptography.DESCryptoServiceProvider"::"New"()
*> Set secret key for DES algorithm.
*> A 64-bit key and an IV are required for this provider.
*>set ls-DES::"Key" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"Key" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)

*> Set the initialization vector.
*>set ls-DES::"IV" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"IV" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)

*> Create the DES decryptor from the DES instance.
set ls-desdecrypt to ls-des::"CreateDecryptor"()

*> Create the crypto stream set to read and to do a DES decryption transform on incoming bytes.

set ls-cryptostream to type "System.Security.Cryptography.CryptoStream"::"New"(ls-fsRead , ls-desdecrypt , type "System.Security.Cryptography.CryptoStreamMode"::"Read")

*> Print out the contents of the decrypted file.
set ls-fsDecrypted to type "System.IO.StreamWriter"::"New"(lnk-OutputFile)
invoke ls-fsDecrypted::"Write"(type "System.IO.StreamReader"::"New"(ls-cryptostream)::"ReadToEnd")
invoke ls-fsDecrypted::"Flush"()
invoke ls-fsDecrypted::"Close"()

goback.
end method "DecryptFile".

One problem that I noticed while rewriting this is that you don't validate the length of the key and IV, both of which must be ls-DES::BlockSize. I've fixed this (trivially) in my version.

Using the key as the IV is a Bad Idea, in terms of security; but I have no idea what your application or threat model is, so I don't know whether that's relevant. (Using DES is itself a Bad Idea for many applications.)


Hi,

I have the following code that encrypts and then i can un-encrypt this file, which works file with text files i.e. readable characters.

However if i try to do this with a stored printed data file that contains unreadable characters it produces garbage.

Is there any way to do this using this .NET class?

method-id "EncryptFile" public static.
01 ls-fsInput type "System.IO.FileStream".
01 ls-fsEncrypted type "System.IO.FileStream".
01 ls-des type "System.Security.Cryptography.DESCryptoServiceProvider".
01 ls-desencrypt type "System.Security.Cryptography.ICryptoTransform".
01 ls-cryptostream type "System.Security.Cryptography.CryptoStream".
01 ls-bytearrayinput type "System.Byte" occurs any.
01 ls-len binary-long.
01 ls-ToBase64Transform type "System.Security.Cryptography.ToBase64Transform".
procedure division using by value lnk-inputfile as string
lnk-Outputfile as string
lnk-key as string.

set ls-fsInput to type "System.IO.FileStream"::"New"(lnk-inputfile , type "System.IO.FileMode"::"Open" , type "System.IO.FileAccess"::"Read")
set ls-fsEncrypted to type "System.IO.FileStream"::"New"(lnk-Outputfile , type "System.IO.FileMode"::"Create" , type "System.IO.FileAccess"::"Write")

set ls-des to type "System.Security.Cryptography.DESCryptoServiceProvider"::"New"()
*
* *> Set secret key for DES algorithm.
* *> A 64-bit key and an IV are required for this provider.
*>set ls-DES::"Key" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"Key" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)
*
* *> Set the initialization vector.
*>set ls-DES::"IV" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"IV" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)
*
* *> Create the DES encryptor from this instance.
set ls-desencrypt to ls-DES::"CreateEncryptor"()
*
* *> Create the crypto stream that transforms the file stream by using DES encryption.
set ls-cryptostream to type "System.Security.Cryptography.CryptoStream"::"New"(ls-fsEncrypted , ls-desencrypt , type "System.Security.Cryptography.CryptoStreamMode"::"Write")
*
* *> Read the file text to the byte array.
compute ls-len = ls-fsInput::"Length"
set size of ls-bytearrayinput to ls-len
invoke ls-fsInput::"Read"(ls-bytearrayinput , 0 , ls-bytearrayinput::"Length")
* *> Write out the DES encrypted file.
invoke ls-cryptostream::"Write"(ls-bytearrayinput , 0 , ls-bytearrayinput::"Length")
invoke ls-cryptostream::"Close"()

goback.
end method "EncryptFile".

method-id "DecryptFile" public static.
01 ls-fsRead type "System.IO.FileStream".
01 ls-fsdecrypted type "System.IO.StreamWriter".
01 ls-desdecrypt type "System.Security.Cryptography.ICryptoTransform".
01 ls-des type "System.Security.Cryptography.DESCryptoServiceProvider".
01 ls-cryptostream type "System.Security.Cryptography.CryptoStream".
01 ls-bytearrayinput type "System.Byte" occurs any.
01 ls-len binary-long.
procedure division using by value lnk-inputfile as string
lnk-Outputfile as string
lnk-key as string.

set ls-fsRead to type "System.IO.FileStream"::"New"(lnk-inputfile , type "System.IO.FileMode"::"Open" , type "System.IO.FileAccess"::"Read")

set ls-des to type "System.Security.Cryptography.DESCryptoServiceProvider"::"New"()
*> Set secret key for DES algorithm.
*> A 64-bit key and an IV are required for this provider.
*>set ls-DES::"Key" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"Key" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)

*> Set the initialization vector.
*>set ls-DES::"IV" to type "System.Text.ASCIIEncoding"::"ASCII"::"GetBytes"(lnk-Key)
set ls-DES::"IV" to type "System.Text.UTF8Encoding"::"UTF8"::"GetBytes"(lnk-Key)

*> Create the DES decryptor from the DES instance.
set ls-desdecrypt to ls-des::"CreateDecryptor"()

*> Create the crypto stream set to read and to do a DES decryption transform on incoming bytes.

set ls-cryptostream to type "System.Security.Cryptography.CryptoStream"::"New"(ls-fsRead , ls-desdecrypt , type "System.Security.Cryptography.CryptoStreamMode"::"Read")

*> Print out the contents of the decrypted file.
set ls-fsDecrypted to type "System.IO.StreamWriter"::"New"(lnk-OutputFile)
invoke ls-fsDecrypted::"Write"(type "System.IO.StreamReader"::"New"(ls-cryptostream)::"ReadToEnd")
invoke ls-fsDecrypted::"Flush"()
invoke ls-fsDecrypted::"Close"()

goback.
end method "DecryptFile".

Well, I have my version working, and it doesn't appear to have a problem with files of any sort.


Here's the source.


      $set sourceformat(variable)
      $set ilusing(System)
      $set ilusing(System.IO)
      $set ilusing(System.Security.Cryptography)
      $set ilusing(System.Text)

       class-id descrypt.

       1 inputFile type FileStream static.
       1 outputFile type FileStream static.
       1 des type DESCryptoServiceProvider static value new DESCryptoServiceProvider.

       method-id Main(args as string occurs any) static.
           if args::Length <> 4
               invoke self::Syntax
           end-if
           declare encrypting as condition-value
           evaluate args(1)
           when "encrypt"
               set encrypting to true
           when "decrypt"
               set encrypting to false
           when other
               invoke self::Syntax
           end-evaluate

           set inputFile to new FileStream(args(3), type FileMode::Open, type FileAccess::Read)
           set outputFile to new FileStream(args(4), type FileMode::Create, type FileAccess::Write)

           declare keySize as binary-long = des::BlockSize / 8
           declare keyBlock as binary-char unsigned occurs any
           set size of keyBlock to keySize
           declare keyBytes = type UTF8Encoding::UTF8::GetBytes(args(2))
           declare copyLen = function min(size of keyBlock, size of keyBytes)
           invoke type Array::Copy(keyBytes, 0, keyBlock, 0, copyLen)
           set des::Key des::IV to keyBlock
           set des::IV to keyBlock

           if encrypting
               invoke self::Encrypt
           else
               invoke self::Decrypt
           end-if
       end method Main.

       method-id Syntax static.
           display "Usage: descrypt encrypt|decrypt key input-file output-file"
           invoke type Environment::Exit(1)
       end method Syntax.

       method-id Encrypt static.
           declare cryptoStream = new CryptoStream(outputFile, des::CreateEncryptor, type CryptoStreamMode::Write)
           invoke inputFile::CopyTo(cryptoStream)
           invoke cryptoStream::Close
           invoke outputFile::Close
       end method Encrypt.

       method-id Decrypt static.
           declare cryptoStream = new CryptoStream(inputFile, des::CreateDecryptor, type CryptoStreamMode::Read)
           invoke cryptoStream::CopyTo(outputFile)
           invoke cryptoStream::Close
           invoke outputFile::Close
       end method Decrypt.

       end class descrypt.


Some things to note:

  • This was tested with Enterprise Developer 2.2 Update 1 and .NET Framework 4.5.
  • I've refactored common code into the Main method.
  • Type and method names do not need to be quoted in current versions of managed COBOL.
  • Use the new operator rather than invoking a constructor directly (type X::New(...)).
  • The CopyTo method (of Stream and its subclasses) is the simplest way to read an entire stream and write it to another stream.
  • The COBOL type binary-char unsigned is the same as the .NET type Byte.
  • My Main method creates an array of the correct size, then copies the key bytes into it, to ensure the Key and IV properties receive an array of the correct size.