Substitution cipher
Substitution Cipher Implementation - File Encryption/Decryption
Task - Here we have to do is there will be a input/source file in which we are going to Encrypt the file by replacing every upper/lower case alphabets of the source file with another predetermined upper/lower case alphabets or symbols and save it into another output/encrypted file and then again convert that output/encrypted file into original/decrypted file. This type of Encryption/Decryption scheme is often called a Substitution Cipher. Click here to know more.
- See also
C#
<lang csharp>using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace SubstitutionCipherProject {
class SubstitutionCipher { static void Main(string[] args) { doEncDec("e:\\source.txt", "enc.txt", true); doEncDec("enc.txt", "dec.txt", false); Console.WriteLine("Done"); Console.ReadKey(); } static void doEncDec(String source, String target, bool IsEncrypt) { ITransform trans;
if (IsEncrypt) trans = new Encrypt(); else trans = new Decrypt();
FileInfo sfi = new FileInfo(source); FileStream sstream = sfi.OpenRead(); StreamReader sr = new StreamReader(sstream);
FileInfo tfi = new FileInfo(target); FileStream tstream = tfi.OpenWrite(); TransformWriter tw = new TransformWriter(tstream, trans); StreamWriter sw = new StreamWriter(tw);
String line; while ((line = sr.ReadLine()) != null) sw.WriteLine(line); sw.Close(); } } public interface ITransform { byte transform(byte ch); } public class Encrypt : ITransform { const String str = "xyfagchbimpourvnqsdewtkjzl"; byte ITransform.transform(byte ch) { if (char.IsLower((char)ch)) ch = (byte)str[ch - (byte)'a']; return ch; } } class Decrypt : ITransform { const String str = "xyfagchbimpourvnqsdewtkjzl"; byte ITransform.transform(byte ch) { if (char.IsLower((char)ch)) ch = (byte)(str.IndexOf((char)ch) + 'a'); return ch; } } class TransformWriter : Stream, IDisposable { private Stream outs; private ITransform trans;
public TransformWriter(Stream s, ITransform t) { this.outs = s; this.trans = t; }
public override bool CanRead { get { return false; } }
public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return true; } } public override void Flush() { outs.Flush(); }
public override long Length { get { return outs.Length; } } public override long Position { get { return outs.Position; } set { outs.Position = value; } } public override long Seek(long offset, SeekOrigin origin) { return outs.Seek(offset, origin); }
public override void SetLength(long value) { outs.SetLength(value); }
public override void Write(byte[] buf, int off, int len) { for (int i = off; i < off + len; i++) buf[i] = trans.transform(buf[i]); outs.Write(buf, off, len); }
void IDisposable.Dispose() { outs.Dispose(); }
public override void Close() { outs.Close(); }
public override int Read(byte[] cbuf, int off, int count) { return outs.Read(cbuf, off, count); } }
}</lang>
REXX
Programming notes: the cipher key (as used by this REXX program) is stored in a file as two records:
- the 1st record is the plain-text characters to be encrypted.
- the 2nd record is the crypt-text characters used for encryption.
- the two records should be equal in the number of characters.
- the Nth character of record 1 will be encrypted to the Nth character of record 2.
<lang rexx>/*REXX program implements a substitution cipher for all records in a file. */ parse arg fid.1 fid.2 fid.3 fid.4 . /*obtain optional arguments from the CL*/ if fid.1== then fid.1= 'CIPHER.IN' /*Not specified? Then use the default.*/ if fid.2== then fid.2= 'CIPHER.OUT' /* " " " " " " */ if fid.3== then fid.3= 'CIPHER.KEY' /* " " " " " " */ if fid.4== then fid.4= 'CIPHER.ORI' /* " " " " " " */ say ' input file: ' fid.1 /*display the fileID used for input. */ say ' output file: ' fid.2 /* " " " " " output. */ say ' cipher file: ' fid.3 /* " " " " " cipher-key*/ say 'decrypted file: ' fid.4 /* " " " " " decrypted*/ call closer /*close all files in case they're open.*/ say
do c=1 while lines(fid.3)\==0 /*read (hopefully 2 records) from key. */ @.c=space(linein(fid.3),0) /*assign input record to an @. array.*/ end /*c*/
c=c-1 /*adjust the number of recores (for DO)*/ if c==0 then call ser fid.3, 'not found or is empty.' if c>2 then call ser fid.3, 'has too many records (>2).' if c<2 then call ser fid.3, 'has too few records (<2).' if length(@.1)\==length(@.2) then call ser fid.3, 'has unequal length records.' call encrypt fid.1, fid.2 /*encrypt the input file ───► output.*/ _=@.1; @.1=@.2; @.2=_ /*switch the cipher keys for decryption*/ call encrypt fid.2, fid.4 /*decrypt the output file ───► decrypt.*/ call show 'cipher file ('fid.3")" , fid.3 /*display the cipher-key file*/ call show 'input file ('fid.1")" , fid.1 /* " " input " */ call show 'output file ('fid.2")" , fid.2 /* " " output " */ call show ' decrypted file ('fid.4")" , fid.4 /* " " decrypted " */ exit /*stick a fork in it, we're all done. */ /*────────────────────────────────────────────────────────────────────────────*/ closer: do f=1 for 4; call lineout fid.f; end /*f*/; return ser: say '***error!*** file ' arg(1)" " arg(2); exit show: say; say center(arg(1),79,'═'); "TYPE" arg(2); return /*────────────────────────────────────────────────────────────────────────────*/ encrypt: parse arg @in,@out; 'ERASE' @out /*delete the output file.*/
do j=1 while lines(@in)\==0 call lineout @out, translate(linein(@in), @.2, @.1) end /*j*/
j=j-1 /*adjust the number of recores (for DO)*/ if j==0 then call ser @in,'is empty.' /*was the file not found or was empty? */ say @in ' records processed: ' j /*show the number of records processed.*/ call closer /*close all the files to be neat & safe*/ return</lang> output when using the default input files:
input file: CIPHER.IN output file: CIPHER.OUT cipher file: CIPHER.KEY decrypted file: CIPHER.ORI CIPHER.IN records processed: 10 CIPHER.OUT records processed: 10 ═══════════════════════════cipher file (CIPHER.KEY)════════════════════════════ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ WXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV ════════════════════════════input file (CIPHER.IN)═════════════════════════════ "Every tool has a specific 'threshold', and when the user exceeds the threshold, the tool becomes a hindrance rather than a help. Any software used beyond its threshold will cause decreases in productivity, not increases. And when individual products are put together piecemeal, the result is a system that has gone past its threshold ─── a counterproductive collection of misfit units that work against each other rather than with each other." ─── Merle Parks ═══════════════════════════output file (CIPHER.OUT)════════════════════════════ "Aranu pkkh dWo W olaYebeY 'pdnaodkhZ', WjZ sdaj pda qoan atYaaZo pda pdnaodkhZ, pda pkkh XaYkiao W dejZnWjYa nWpdan pdWj W dahl. wju okbpsWna qoaZ XaukjZ epo pdnaodkhZ sehh YWqoa ZaYnaWoao ej lnkZqYperepu, jkp ejYnaWoao. wjZ sdaj ejZereZqWh lnkZqYpo Wna lqp pkcapdan leaYaiaWh, pda naoqhp eo W ouopai pdWp dWo ckja lWop epo pdnaodkhZ ─── W YkqjpanlnkZqYpera YkhhaYpekj kb ieobep qjepo pdWp skng WcWejop aWYd kpdan nWpdan pdWj sepd aWYd kpdan." ─── Ianha LWngo ═════════════════════════ decrypted file (CIPHER.ORI)══════════════════════════ "Every tool has a specific 'threshold', and when the user exceeds the threshold, the tool becomes a hindrance rather than a help. Any software used beyond its threshold will cause decreases in productivity, not increases. And when individual products are put together piecemeal, the result is a system that has gone past its threshold ─── a counterproductive collection of misfit units that work against each other rather than with each other." ─── Merle Parks