In a previous post, The Math That Enables Asymmetric Key Cryptography, I discussed how your web browser and a web server can establish an encrypted communication channel without requiring you and the web administrator to meet beforehand to exchange secret keys. I explained how your web browser and a web server exchange public keys, then perform math operations on their private keys and the exchanged public keys to derive the same shared key. And I emphasized the security of this technique (Diffie-Hellman Key Exchange) is guaranteed by the computational difficulty of determining the shared key from the partial information transmitted over the network. I explained this but did not actually encrypt anything.

OK, let’s do that now. First, let’s write the Main method to a Console program. We’ll use Client and Server objects to clarify on which machine various code executes.

The above code prompts the user for a message to send from a client machine to a server. It doesn’t get into any details about encryption and decryption. We’ll fill that in as we go. To keep things simple, I will implement the entire program in a single executable running on a single machine. By imagining the client and server are running on separate machines we avoid getting bogged down in a lot of networking code that distracts from the lesson:

How to use the shared key derived by Diffie-Hellman Key Exchange to encrypt and decrypt messages.

Let’s write the Client class.

The above code implements the Diffie-Hellman Key Exchange we’ve already seen in my previous post, but in a more object oriented style. It calls the server’s ReceiveClientPublicKey method. The server responds with its public key. In addition, the Client calls EncryptMessage and DecryptMessage methods implemented in a base class, which we’ve not yet written.

The above code uses the PublicKey class to hold data transmitted to and from the client and server.

Let’s write the Server class.

Similar to the Client class, the above code implements the Diffie-Hellman Key Exchange we’ve already seen, but in a more object oriented style. Likewise, it calls DecryptMessage and EncryptMessage methods implemented in a base class. Finally, it knows how to respond to some memorable lines from a very funny film.

Now let’s write the base class that contains the encrypt and decrypt methods. Before writing the code, let’s discuss how to apply a very simple cipher to a message using a key (the shared key derived from the Diffie-Hellman Key Exchange).

How Ciphers Function

When I say “simple” I mean it: Our cipher will be XOR. XOR means “exclusive or.” It’s a logical operation performed on two bytes: Each bit in an eight-bit byte is compared to the corresponding bit in another byte. If exactly one of the bits (doesn’t matter which one) is set, then the corresponding bit in the resulting byte is set (to 1). If not, then the corresponding bit in the resulting byte is cleared (set to 0). I’ll illustrate the operation in a table.

Message E r i k
UTF-8 Character Number (Decimal) 69 114 105 107
UTF-8 Character Number (Binary) 01000101 01110010 01101001 01101011 XOR
Key 11011110 01111110 11111010 00111011
Result (Encoded Message) 10011011 00001100 10010011 01010000

Ciphers function on byte arrays- sequences of bits (1s and 0s). Reading the above table one column at a time, from the top row to the bottom row, we see a character, it’s numerical representation in the UTF-8 encoding, the corresponding key bits, and the XOR of the character bits with the key bits.

Why did I chose the XOR bitwise operator for our cipher? Because it’s reversible. If we XOR the encoded message with the key, we get back the original message.

Encoded Message 10011011 00001100 10010011 01010000 XOR
Key 11011110 01111110 11111010 00111011
Result (UTF-8 Binary) 01000101 01110010 01101001 01101011
Result (Original Message) E r i k

With that knowledge, let’s write our cipher functions. We’ll place them in a base class common to Client and Server, since they’re needed by both.

Let’s run our program. Data transmitted between the client and the server is printed in yellow text. This makes it easy to distinguish values transmitted over a network (that could be intercepted by a malicious party) from values present in the client or server’s memory.

Client:
G = 7459164945958487103247514958695088522428872714430035713376778340819025435755225299390016451299625904995610747436862628659796459871891392067490882856281131673481614855284270389935322207729348782486922388462155050974810183270983531702203687051003259355646417838936040226014340478188550773318175437771720440001
N = 66038518493806840352972810592435437632325488189975352610256674598053934576510260402833273741967331332955288303098012395256454759210330183314998765937483085267046209433966666095043249085975296634849047071263616528047210254254599136168961093599065529809715047866605038360579409749185471683803725681381084012332
M = 33486301366456563696218115781901541398662420000429900171687597278544775913383462855201810148231185510832983920111033409943309514699813030704523876005163895347127645372934144050797383484903732156543239857571623187020297531606261799620329201184519756300928127402805025058861678144209012607523275728899614568545

Server:  SharedKey = 47073655159134918134185073460199681436922280188019642377656969266568063354497830417074149699789022178062187019792126959906529838965745558482088461855562978304311706849152096760407519932338044035089398495877963335140385940745118066469170063580897367882785775341539530474821791738395029729064726752072659067469.

Server:
G = 7459164945958487103247514958695088522428872714430035713376778340819025435755225299390016451299625904995610747436862628659796459871891392067490882856281131673481614855284270389935322207729348782486922388462155050974810183270983531702203687051003259355646417838936040226014340478188550773318175437771720440001
N = 66038518493806840352972810592435437632325488189975352610256674598053934576510260402833273741967331332955288303098012395256454759210330183314998765937483085267046209433966666095043249085975296634849047071263616528047210254254599136168961093599065529809715047866605038360579409749185471683803725681381084012332
M = 10631618743049162633968514894912319860142582925322288989585957148617941590616758071972614142552891218705758728668329840700266811668038454652729287119525319115374328406557151081317533984780322309696426518991630130483831935600155248529950946942885532136098394941972994803418607263271162544694554996149686868029

Client:  SharedKey = 47073655159134918134185073460199681436922280188019642377656969266568063354497830417074149699789022178062187019792126959906529838965745558482088461855562978304311706849152096760407519932338044035089398495877963335140385940745118066469170063580897367882785775341539530474821791738395029729064726752072659067469.


Enter a message to send to server:  Roger.

Client:  Sending encrypted message  "Hw1YO4PN"

Server:  Received encrypted message "Hw1YO4PN"

Server:  Decrypted message is       "Roger."

Server:  Sending encrypted message  "BRdXYQ=="

Client:  Received encrypted message "BRdXYQ=="

Client:  Decrypted message is       "Huh?"

Some more encrypted Airplane! dialog.

Client:
G = 5558502683609592898214381570457582669694626092600746243044449908456969330101295451238361832434200143490423440295979024278306485460590162535079624843122527295019701285111389625580845028562654075798917874570383016893682792589244078017914002713837989762771102196879505707135339109878808695477789643370461174535
N = 19354160029733273630108151214143139638436780914293788103417495596622413082552091051184157679889314999226630744827340578723661050234437047014781133036763876260304770835648976082707164424376980890228365052502789054700076865905663098715652620119889462227749402096943775434641964551568416659862954591360156965284
M = 14505723345735102892607184351276920382015810669805032428079154199318034811206151404039890930031158293976210042472225162428544969385581865394279798733447713443650739097619919369499725270546244545623797606342983922018415948218260845845115604962636448931878530811592322262489468146888185396790948028886144148051

Server:  SharedKey = 7833323696301415156880305670329732633812349816244439519710299827419873507512354286723699456065074920193443728613904114168295846081315150223189137185644029208353084925347690245577348032555533461732470738836449668359441221060713077575108592660334175336205699642075428107805938400250869931449520841948225853677.

Server:
G = 5558502683609592898214381570457582669694626092600746243044449908456969330101295451238361832434200143490423440295979024278306485460590162535079624843122527295019701285111389625580845028562654075798917874570383016893682792589244078017914002713837989762771102196879505707135339109878808695477789643370461174535
N = 19354160029733273630108151214143139638436780914293788103417495596622413082552091051184157679889314999226630744827340578723661050234437047014781133036763876260304770835648976082707164424376980890228365052502789054700076865905663098715652620119889462227749402096943775434641964551568416659862954591360156965284
M = 6329658948705739923970541243065929137805821704672538873114091315012804012687534143931159044653349856619435543953751781098323260563896881674814057380717098500113370107638654836825506915938398179036001733989482530033643296722435806386223061619028026850693620511989182471082291051512719501157512586259310870353

Client:  SharedKey = 7833323696301415156880305670329732633812349816244439519710299827419873507512354286723699456065074920193443728613904114168295846081315150223189137185644029208353084925347690245577348032555533461732470738836449668359441221060713077575108592660334175336205699642075428107805938400250869931449520841948225853677.


Enter a message to send to server:  Request vector.  Over.

Client:  Sending encrypted message  "v70SIiARllpKaS53TDODSPDLX8aNrQ=="

Server:  Received encrypted message "v70SIiARllpKaS53TDODSPDLX8aNrQ=="

Server:  Decrypted message is       "Request vector.  Over."

Server:  Sending encrypted message  "urACI3o="

Client:  Received encrypted message "urACI3o="

Client:  Decrypted message is       "What?"

More funny lines. The hackers are missing out on some good laughs because they can’t read any of this.

Client:
G = 53069370197024238219531524203942933508648220608445487047074707183138681816570747647893033836251138521703350865846098668938216168411181403261810544215997195324176379510190291487339923522232255542603836754312433847828506522925626504783633532449824657910803719320681027879952599762642726625534067935554961516331
N = 51179309874707199813139291635199337284021497617677909894433790520917217327508068836384895273432940728574235889922301704155863091859695002564780551707933705977943533563464956953545865085702830812016012903131295992376519931146004756912080622199956057325185084744371658684896346279487819548260823380705410814559
M = 15023037524142511525098648955994193100099729358855783722166776897705090615736713838982262176318833393512030787017721099481168101640486052011056477099897464035624179232619917820549213921691777530473353913162458906635747541377545495523026094229507811800755865811083444774954674247172665557821855724398624663190

Server:  SharedKey = 23442904020218907802327841205723372951810471845848128502156424716884589598912425286253242427172594150299754562842955803187618445310668160701248888095295377753176360193280528055371871811953909377787872519824727495331958623350910757344349753646582823726680485215361779304603826607559360153283865603551941961473.

Server:
G = 53069370197024238219531524203942933508648220608445487047074707183138681816570747647893033836251138521703350865846098668938216168411181403261810544215997195324176379510190291487339923522232255542603836754312433847828506522925626504783633532449824657910803719320681027879952599762642726625534067935554961516331
N = 51179309874707199813139291635199337284021497617677909894433790520917217327508068836384895273432940728574235889922301704155863091859695002564780551707933705977943533563464956953545865085702830812016012903131295992376519931146004756912080622199956057325185084744371658684896346279487819548260823380705410814559
M = 17561252264158204132750083798930011786740996945338164968331080762216784793066372849652540922374825727151105098046101277093022011328235731072204646520046365749233819062374446851571381212418619927012778132385251412754469212365116690248705988337929644044325146356562245826275772734077850202553001062828323279816

Client:  SharedKey = 23442904020218907802327841205723372951810471845848128502156424716884589598912425286253242427172594150299754562842955803187618445310668160701248888095295377753176360193280528055371871811953909377787872519824727495331958623350910757344349753646582823726680485215361779304603826607559360153283865603551941961473.


Enter a message to send to server:  We have clearance, Clarence.

Client:  Sending encrypted message  "VkLdll+G+vglh9NBt7OAsmTjzaL6QNdP2hvhsg=="

Server:  Received encrypted message "VkLdll+G+vglh9NBt7OAsmTjzaL6QNdP2hvhsg=="

Server:  Decrypted message is       "We have clearance, Clarence."

Server:  Sending encrypted message  "U0iam0zcv4opjNNS6/LOhmmumcblAcpfxljy+b1JcQgynI8Hu3LpjTE="

Client:  Received encrypted message "U0iam0zcv4opjNNS6/LOhmmumcblAcpfxljy+b1JcQgynI8Hu3LpjTE="

Client:  Decrypted message is       "Roger, Roger.  What's our vector, Victor?"

And the most famous line from the film.

Client:
G = 4297386783487735414846693145450771189559738018014892682456076229360833256501405013800897170127870175517007363004919799002177618015833309016189450313935408389006791614377339610264521592889256664232676485535821934618684407829934356561662253451043049049780447444932050245559598281296720020117823330051941050747
N = 19729186273402551800438552878194303631411875635295034800056259604070809350890814744954475384068004730598094802495534068798704815335417606030625926796137140921690078474628081873045989279077345756420186204503400380013192567398222424266821049485696141599683511015067817624931686538248583279045132909905477520360
M = 12641238712946091348407256593415302292067547753629647795738579024337002478450103331189426311378025449669278393153950821401705454520478631030068234295887085235906358133100616954465107512957868625332640661596603051637637020783510550369795202499007149404083707031298023302877096399886497125925644491627644808929

Server:  SharedKey = 8087363388367535170449586496700371262016435420005315648369503769365785594647070671956931837125866899635421660776522959671231881662806739501425208815006659451495366725183040925037530375267109982506018586135346911247773232647992057405238685892638765894785785574400303336398293793374645014537787442379795726929.

Server:
G = 4297386783487735414846693145450771189559738018014892682456076229360833256501405013800897170127870175517007363004919799002177618015833309016189450313935408389006791614377339610264521592889256664232676485535821934618684407829934356561662253451043049049780447444932050245559598281296720020117823330051941050747
N = 19729186273402551800438552878194303631411875635295034800056259604070809350890814744954475384068004730598094802495534068798704815335417606030625926796137140921690078474628081873045989279077345756420186204503400380013192567398222424266821049485696141599683511015067817624931686538248583279045132909905477520360
M = 13090530100015977803555793272224195990750850699122528898463154134812456165393357161978034787939297264898454517060142165551546143957792549803346169687396270721362063330023250493624154252707982325228960662490111495694657187911507778734222822041183325898628659568209583333990405368655369264668562797398034980107

Client:  SharedKey = 8087363388367535170449586496700371262016435420005315648369503769365785594647070671956931837125866899635421660776522959671231881662806739501425208815006659451495366725183040925037530375267109982506018586135346911247773232647992057405238685892638765894785785574400303336398293793374645014537787442379795726929.


Enter a message to send to server:  Surely you can't be serious?

Client:  Sending encrypted message  "AncmJpCsUy2hzN6EpUIi/L+rCzAdXP1Kzztecw=="

Server:  Received encrypted message "AncmJpCsUy2hzN6EpUIi/L+rCzAdXP1Kzztecw=="

Server:  Decrypted message is       "Surely you can't be serious?"

Server:  Sending encrypted message  "GCI1LtymFian1ouU6gwlyfGtTnQBV6hXgC1MIExl4Dgs7+ni2ozBnIY="

Client:  Received encrypted message "GCI1LtymFian1ouU6gwlyfGtTnQBV6hXgC1MIExl4Dgs7+ni2ozBnIY="

Client:  Decrypted message is       "I am serious.  And don't call me Shirley."

You may review the full source code in the Encrypt Decrypt folder of my Sandbox project in GitHub.

There’s a weakness in our simple XOR cipher that’s exposed by sending a message not recognized as a line from Airplane! I’ll discuss the weakness and potential improvements in a later post.

See the next post in this series, AES, A Stronger Cipher Than XOR.

Leave a Reply

Your email address will not be published. Required fields are marked *