Substitution cipher: Difference between revisions
m (→{{header|J}}) |
m (→{{header|J}}) |
||
Line 165: | Line 165: | ||
<lang J>keysubst=: [`(a.i.])`(a."_)} |
<lang J>keysubst=: [`(a.i.])`(a."_)} |
||
key=: 'Taehist' keysubst '!@#$%^&' |
key=: 'Taehist' keysubst '!@#$%^&' |
||
enc=: a. {~ key |
enc=: a. {~ key i. ] |
||
dec=: key {~ a. |
dec=: key {~ a. i. ] |
||
enc 'This is a test.' |
enc 'This is a test.' |
Revision as of 14:46, 15 October 2015
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>
J
Example implementation:
<lang J>keysubst=: [`(a.i.])`(a."_)} key=: 'Taehist' keysubst '!@#$%^&' enc=: a. {~ key i. ] dec=: key {~ a. i. ]
enc 'This is a test.'
!$%^ %^ @ &#^&.
dec '!$%^ %^ @ &#^&.'
This is a test.</lang>
Note that this particular implementation bakes the key itself into the implementations of enc
and dec
. Also note that this particular key is rather limited - letters not mentioned in the key encrypt as another identical character. That seems to be sufficient, given the current task description. But of course other approaches are also possible...
Racket
Uses #REXX input file (in data/substitution.in.txt).
The check-equal? tests assure us that we return the plain text after a cypher/decypher pair; so I don't display the plaintext in the output.
<lang racket>#lang racket/base (require racket/list racket/function racket/file)
(define abc "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
- Used to generate my-key for examples
(define (random-key (alphabet abc))
(list->string (shuffle (string->list alphabet))))
(define (cypher/decypher key (alphabet abc))
;; alist is fine, hashes are better over 40 chars... so alist for ;; abc, hash for ASCII. (define ab-chars (string->list alphabet)) (define ky-chars (string->list key)) (define cypher-alist (map cons ab-chars ky-chars)) (define decypher-alist (map cons ky-chars ab-chars)) (define ((subst-map alist) str) (list->string (map (lambda (c) (cond [(assoc c alist) => cdr] [else c])) (string->list str)))) (values (subst-map cypher-alist) (subst-map decypher-alist)))
(define (cypher/decypher-files key (alphabet abc))
(define-values (cypher decypher) (cypher/decypher key alphabet)) (define ((convert-file f) in out #:exists (exists-flag 'error)) (curry with-output-to-file out #:exists exists-flag (lambda () (display (f (file->string in)))))) (values (convert-file cypher) (convert-file decypher)))
(module+ test
(require rackunit) (define my-key "LXRWzUrIYPJiVQyMwKudbAaDjSEefvhlqmOkGcBZCFsNpxHTgton") (define-values (cypher decypher) (cypher/decypher my-key abc)) (define in-text #<<T
The quick brown fox... .. jumped over the lazy dog! T
) (define cypher-text (cypher in-text)) (define plain-text (decypher cypher-text)) (displayln cypher-text) (check-equal? plain-text in-text) (define-values (file-cypher file-decypher) (cypher/decypher-files my-key abc)) (file-cypher "data/substitution.in.txt" "data/substitution.crypt.txt" #:exists 'replace) (file-decypher "data/substitution.crypt.txt" "data/substitution.plain.txt" #:exists 'replace) (displayln "---") (displayln (file->string "data/substitution.crypt.txt")) (check-equal? (file->string "data/substitution.in.txt") (file->string "data/substitution.plain.txt")))</lang>
- Output:
dmh sHOfG eNCgZ lCt... .. kHBFhv CThN xmh cEno vCq! --- "zThNo xCCc mEp E pFhfOlOf 'xmNhpmCcv', EZv gmhZ xmh HphN htfhhvp xmh xmNhpmCcv, xmh xCCc ehfCBhp E mOZvNEZfh NExmhN xmEZ E mhcF. LZo pClxgENh Hphv ehoCZv Oxp xmNhpmCcv gOcc fEHph vhfNhEphp OZ FNCvHfxOTOxo, ZCx OZfNhEphp. LZv gmhZ OZvOTOvHEc FNCvHfxp ENh FHx xCqhxmhN FOhfhBhEc, xmh NhpHcx Op E popxhB xmEx mEp qCZh FEpx Oxp xmNhpmCcv ─── E fCHZxhNFNCvHfxOTh fCcchfxOCZ Cl BOplOx HZOxp xmEx gCNG EqEOZpx hEfm CxmhN NExmhN xmEZ gOxm hEfm CxmhN." ─── VhNch MENGp
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