Secure mail
?Mike May, S. J., 2002, maymk@slu.edu
> restart;
We want to look at sending a collection of concepts we have been working on in class for an application like sending and receiving secured mail. We will use DES as our symmetric block cipher and RSA as our public key cipher.
The intent is to be able to send an encrypted message over an open channel in such a way that it is secure from eavesdropping, and such that the intended recipient knows who sent the message and that it has not been tampered with. (The recipient should be assured to both message integrity and authenticity.)
>
Encrypting the message
We start with a message that we will be sending.
> message := "This is an attempt to look at a reasonable way to send a message
> in such a way that it is encrypted, but that the receiver can also revify that
> the message is really from me, and that no one has tampered with it after I
> signed the message. There are several pieces to deal with. I need to hash
> the message down to a digest of reasonable length. We will do that with DES.
> After we have a hashed digest, we sign it with RSA. Then, since I want to have
> the message decrypted by the intended recipient alone, I encrypt the session key
> with RSA and the receiver's public key. x":
We want to encrypt the message with DES used in Cipher Block Chaining mode. You can either rerun the DES constants and DES functions worksheets to load the constants and commands, or you can read them in from a file. To read the DES.m file, you need to copy the file to the current directory. On a Macintosh, that is the directory with the Maple application. The current directory can be determined by the currentdir() command.
> currentdir();
"C:\maple"
Either copy DES.m to the current directory before proceeding or create it on your own machine by running the DESConstants.mws and DESFunctions.mws worksheets.
> read `DES.m`;
To prepare the message for encryption with DES, we want to break it into hex words of 64 bits. Each word corresponds to 8 ASCII characters, so we pad the message out with null characters so that the number of characters is divisible by 8. We also record the number of words.
> messLength := length(message);
> messWords := ceil(messLength/8);
> messPadding := 8*messWords - messLength;
messLength := 577
messWords := 73
messPadding := 7
> messList := convert(message, bytes):
> messList := [op(messList),seq(0,i=1..messPadding)]:
> intTo2Hex := intVal -> substring(convert(intVal+256,hex),2..3):
> messHexList := map(intTo2Hex,messList):
> messHexWordList := [seq(cat(seq(messHexList[8*i+j],j=1..8)),i=0..messWords-1)];
messHexWordList := [5468697320697320, 616E20617474656D,
707420746F206C6F, 6F6B206174206120, 726561736F6E6162,
6C65207761792074, 6F2073656E642061, 206D657373616765,
0A696E2073756368, 2061207761792074, 6861742069742069,
7320656E63727970, 7465642C20627574, 2074686174207468,
6520726563656976, 65722063616E2061, 6C736F2072657669,
667920746861740A, 746865206D657373, 6167652069732072,
65616C6C79206672, 6F6D206D652C2061, 6E64207468617420,
6E6F206F6E652068, 61732074616D7065, 7265642077697468,
2069742061667465, 7220490A7369676E, 656420746865206D,
6573736167652E20, 2054686572652061, 7265207365766572,
616C207069656365, 7320746F20646561, 6C20776974682E20,
2049206E65656420, 746F20686173680A, 746865206D657373,
61676520646F776E, 20746F2061206469, 67657374206F6620,
726561736F6E6162, 6C65206C656E6774, 682E202057652077,
696C6C20646F2074, 6861742077697468, 204445532E0A4166,
7465722077652068, 6176652061206861, 7368656420646967,
6573742C20776520, 7369676E20697420, 7769746820525341,
2E20205468656E2C, 2073696E63652049, 2077616E7420746F,
2068617665200A74, 6865206D65737361, 6765206465637279,
7074656420627920, 74686520696E7465, 6E64656420726563,
697069656E742061, 6C6F6E652C204920, 656E637279707420,
7468652073657373, 696F6E206B65790A, 7769746820525341,
20616E6420746865, 2072656365697665, 722773207075626C,
6963206B65792E20, 7800000000000000]
To encrypt this message with DES in CBC mode I need a key and an initial value. We choose the key at random. (This ignores the fine point that every eighth bit of a key should be a parity bit.)
> randKey := substring(convert(2^64+rand(2^64)(),hex),2..17);
randKey := 7778EEFFF432E596
In order to reproduce results we record the key as 7778EEFFF432E596. We expand this key with the command from the DES worksheets.
> randKey := "7778EEFFF432E596":
> key := keyexpander(randKey):
Our initial value will be the zero word encrypted with our key.
> allZeroes := substring(convert(2^64+0,hex),2..17);
> IV := qdDEShex(allZeroes,key);
allZeroes := 0000000000000000
IV := "04844CB2337C0CC2"
We now encrypt the message with with DES in CBC mode. The first word uses the initial value and the first word of the message. The rest of the message in then encrypted in a loop
> cipherTable[1] := qdDEShex(xor64hex(IV,messHexWordList[1]),key);
> for i from 2 to messWords do
> cipherTable[i] := qdDEShex(xor64hex(cipherTable[i-1],messHexWordList[i]),key):
> od:
cipherTable[1] := CFE5523C29D556BF
Time for a technical adjustment. We want to convert the format of the encrypted message from a table to a list.
> cipherList := convert(cipherTable,list);
cipherList := [CFE5523C29D556BF, 96F0272D4A3A54E4, 7EB9FE4EDA6BB7F5,
97AE9F3B9962C5A5, 1347D0568C88B728, C623BCA4F38195DC,
F933A4B073ED3112, B91012489AC26DAE, EFD8057D6FD221BD,
1295F50C701D1D2A, 6F6DFA21417FAA4A, 7141B83C93FD20B6,
E69DCE99E7250748, FE176522609FF31B, 4A4C6F06D3777871,
AF0F92A74F6BEC46, 62FD8DDE9EE32D60, "0CB6D35244F2E442",
6A967981EA02B712, 72CC1609326E70E8, B0DED0ECA222C388,
752B36EFD2577F58, 453BB651C1E38943, 281EAA993BC733C8,
266339ECE05AEC2B, F042F363E0407FC0, 399568B48B4DEE1B,
6795E99D5464A384, BC17EAAC8D5E4668, D1350C559437085C,
8A713C993AC9797F, 409D82BB0A4E31E9, DB5C8F9438DD8E47,
F0FAB6F37EC1D37E, 2ABA3EB9FD4F2880, 46416F72365B3D50,
B85739A2776D053F, 84FC96A4F62FAC39, 5ABF5E07AA8AD34E,
A0FDF3499984D67F, F3FCD3D6AC6AEF93, A14644D8C85838D1,
E7D72469150DBA19, 2E1D829A60388C20, 6718F326DB8347C4,
3E0135B8172EB1DC, B0628989325F47F9, 4F43A4AE9F3A3E8A,
9B734D47D058A4FA, 10D0EC2185334AA9, 57DD05A568A1298A,
F3950DBD3FD36DD1, "0001188AEE7CE1F2", 919E055417230178,
65E51F33A12038C2, 9CAB5B56319968D5, 541D06B4F4BED47A,
37CB3A45D199698E, "077BAFF5CA62F4B8", E75D714902E9AF89,
A587EDFFCD7870A1, 13D9E0208439CA65, 8FA36034F7CFB55D,
5FE1295449ED3D04, "074B76973A2AD3CA", 3240DED15561C814,
9700F1A93DB61F1E, "0B1A9419B9D4DEDE", C7541B456A78272F,
B6919537C24376E3, D3EC4451D3A8B3B6, 29D4B2C2FF8D4A48,
7C54E08D43AEC1AF]
Thus we have encrypted the message.
Signing the hash and encrypting the session key
For the purpose of digital signatures, we will consider the last word of the message to be the hash of the message.
> hash := cipherList[messWords];
hash := 7C54E08D43AEC1AF
We want to use RSA for two functions. We want to encrypt the session key so our recipient can decrypt the message. We also want to sign the hash. To sign the hash with RSA we produce our primes and our public n. We then set 2^16 + 1 as our standard encryption key, and we compute d.
> p := nextprime(rand(10^80)());;
> q := nextprime(rand(10^80)());;
p := 33073697474256143563558458718976746753830538032062222085722\
974121768604305614073
q := 80037409259811952655310075487163797179490457039169594160088\
430571674960498834131
> Senderp := 33073697474256143563558458718976746753830538032062222085722974121768604305614073:
> Senderq := 80037409259811952655310075487163797179490457039169594160088430571674960498834131:
> Sendern := Senderp*Senderq;
> Sendere := 2^16+1;
> Senderd := (1/Sendere) mod ((Senderp-1)*(Senderq-1)):
Sendern := 26471330604822478554767314516351292234851316805313644\
1607820278334526819450073873355024584847059403376446989563\
0694651936487340877088430911072869585934526325563
Sendere := 65537
We publish (Sendern, Sendere) as our public key. To sign the hash we encrypt the hash with our decryption key.
> digestNum := convert(hash, decimal, hex);
> signature := Power(digestNum,Senderd) mod Sendern;
> sigHex := convert(signature, hex);
digestNum := 8959032456077296047
signature := 245983702794116089362368757483423329734528006134782\
1985662630566244061843365372094345427503003489339669595275\
672440552327927929160602299359970568038871273291070
sigHex := 2CCA706E7E7864A48915A4B0A2A3EF20D56C920BD79B48B15B66B9\
82576BEB3688415EECC0474C48649ED7AC322A9DFD7E811221FFB0DA8E\
C67B66EF51C721323BD3E
To encrypt the session key, we need the receiver's public key, (Receivern, Receivere).
> p := nextprime(rand(10^80)());;
> q := nextprime(rand(10^80)());;
p := 20457916453747019461644031395307920624947349951053530086146\
486307198155590763471
q := 92673709525428510973272600608981219760099374675982933766845\
473509473676470788363
> Receiverp := 20457916453747019461644031395307920624947349951053530086146486307198155590763471:
> Receiverq := 92673709525428510973272600608981219760099374675982933766845473509473676470788363:
> Receivern := Receiverp*Receiverq;
> Receivere := 2^16+1:
> Receiverd := (1/Receivere) mod ((Receiverp-1)*(Receiverq-1));
Receivern := 189591100693003582111364552976788405725928381847773\
9524604309139408303387651699653989993189557809168785274595\
534506647543454372607114206130735004084228432287973
Receiverd := 169343788277874234243786841053988429351120674071211\
5542232434325689049906256850141489038249559147237792431756\
203690286006890242858457518226919479389457234083833
> keyNum := convert(randKey, decimal, hex);
> encryptKey := Power(keyNum, Receivere) mod Receivern:
> encryptKeyHex := convert(encryptKey, hex);
keyNum := 8608893470799750550
encryptKeyHex := 10F36CDAE57F665A367984588EC59ACACFD57D31338F7C1\
19F57E5AFE25B13E06BB669508542CE257DB955EE4BD8840830EE5C728\
A470EEC8E267BBCB113000F29C5E
The message
>
Putting things together we have our message.
cipherList := [CFE5523C29D556BF, "96F0272D4A3A54E4", "7EB9FE4EDA6BB7F5", "97AE9F3B9962C5A5", "1347D0568C88B728", C623BCA4F38195DC, F933A4B073ED3112, B91012489AC26DAE, "88AC794BF81A3613", "027979270A6CE25E", "1FF04858A850FB18", "72B6F715E5F0B050", "302DA487928942DD", "400825FF341D62FF", "25BAB3DFAA300C6E", DF6548D262CCDB76, "155112EEC2A35653", "3626EB94C9508387", F923D7D04BA91C3C, "4541DD7ED88DF681", B80954BD64B25BD1, E5DDE2260FA80D54, "553431C417C63262", "238AEC42B48D39F9", "001F68168A03DC79", F0F26735387BEAFE, ABF29815E6EEF280, "1CE591E013397E46", AE253A8F2CB920F5, "6CDD5CF57DB814E9", "538EDF12831AAF07", D16DA28C099FBCD2, "16EA042321E8C07C", "4B4E3A3A240CD134", "008A4839BB5A902A", "1D9EF4F67B9D790F", "315D4ABFE6FD552A", "5B8EC53DB56BE2F0", "8764D129BE79A2AE", E468BD18F31EFC89, "041B1B2EDD8609F2", "94084157231C1D69", "7592C6C37E571E88", "1AE32E4143FDBD02", "4F46C82DF30E8C7B", C4CEC8AC4B918453, "43B15827F8831008", F47E5AA003E98FEC, "5B2581BC8F0D5FD8", "2463B68E42F65963", "614F5FEFF34EECE6", "1F5FBB2D65D5D1B0", EE611B55060418A9, "78EDFE10B983D58F", E0DCBAE6A02405A2, "089157D36419A8A8", A82D7722C7302B21, "755443BF881CDAA8", "9F9A275493C95772", "673AF1ED886F45FA", "1666C6E7E5F342ED", C44E2FB386806250, EC429290D9DE3961, D69AFA699BC1B350, A558FC5AD6134C13, "3836A716B9D63336", FAA592E49F503D7B, "793C737ADDBD5ECE", "00912BAFAE5F4E4F", "1C297C183126E230", "6A69015002985748", "01A14542FEBCBC8E", D058ADE681825447];
hash := D058ADE681825447;
sigHex := "151746B988F8A7879A20548871F96A4D40CE8CBFB826381F26183F2209C8D4E75460CC3617781B018BEF0DB767E18ECE809551514E0479C54F188697160FCD867C088"
encryptKeyHex := "10F36CDAE57F665A367984588EC59ACACFD57D31338F7C119F57E5AFE25B13E06BB669508542CE257DB955EE4BD8840830EE5C728A470EEC8E267BBCB113000F29C5E";
Sendern := 2647133060482247855476731451635129223485131680531364416078202783345268194500738733550245848470594033764469895630694651936487340877088430911072869585934526325563
Sendere := 65537
>
Reading the message
To put ourselves in the position of the receiver, we restart to clear the memory. The receiver knows the public key of the sender and the receiver's private key. The receiver also has our message.
> restart;
> read `DES.m`:
> Receivern := 1895911006930035821113645529767884057259283818477739524604309139408303387651699653989993189557809168785274595534506647543454372607114206130735004084228432287973:
> Receiverd := 1693437882778742342437868410539884293511206740712115542232434325689049906256850141489038249559147237792431756203690286006890242858457518226919479389457234083833:
> Sendern := 2647133060482247855476731451635129223485131680531364416078202783345268194500738733550245848470594033764469895630694651936487340877088430911072869585934526325563:
> Sendere := 65537:
> cipherList := [CFE5523C29D556BF, "96F0272D4A3A54E4", "7EB9FE4EDA6BB7F5", "97AE9F3B9962C5A5", "1347D0568C88B728", C623BCA4F38195DC, F933A4B073ED3112, B91012489AC26DAE, "88AC794BF81A3613", "027979270A6CE25E", "1FF04858A850FB18", "72B6F715E5F0B050", "302DA487928942DD", "400825FF341D62FF", "25BAB3DFAA300C6E", DF6548D262CCDB76, "155112EEC2A35653", "3626EB94C9508387", F923D7D04BA91C3C, "4541DD7ED88DF681", B80954BD64B25BD1, E5DDE2260FA80D54, "553431C417C63262", "238AEC42B48D39F9", "001F68168A03DC79", F0F26735387BEAFE, ABF29815E6EEF280, "1CE591E013397E46", AE253A8F2CB920F5, "6CDD5CF57DB814E9", "538EDF12831AAF07", D16DA28C099FBCD2, "16EA042321E8C07C", "4B4E3A3A240CD134", "008A4839BB5A902A", "1D9EF4F67B9D790F", "315D4ABFE6FD552A", "5B8EC53DB56BE2F0", "8764D129BE79A2AE", E468BD18F31EFC89, "041B1B2EDD8609F2", "94084157231C1D69", "7592C6C37E571E88", "1AE32E4143FDBD02", "4F46C82DF30E8C7B", C4CEC8AC4B918453, "43B15827F8831008", F47E5AA003E98FEC, "5B2581BC8F0D5FD8", "2463B68E42F65963", "614F5FEFF34EECE6", "1F5FBB2D65D5D1B0", EE611B55060418A9, "78EDFE10B983D58F", E0DCBAE6A02405A2, "089157D36419A8A8", A82D7722C7302B21, "755443BF881CDAA8", "9F9A275493C95772", "673AF1ED886F45FA", "1666C6E7E5F342ED", C44E2FB386806250, EC429290D9DE3961, D69AFA699BC1B350, A558FC5AD6134C13, "3836A716B9D63336", FAA592E49F503D7B, "793C737ADDBD5ECE", "00912BAFAE5F4E4F", "1C297C183126E230", "6A69015002985748", "01A14542FEBCBC8E", D058ADE681825447]:
> sigHex := "151746B988F8A7879A20548871F96A4D40CE8CBFB826381F26183F2209C8D4E75460CC3617781B018BEF0DB767E18ECE809551514E0479C54F188697160FCD867C088":
> encryptKeyHex := "10F36CDAE57F665A367984588EC59ACACFD57D31338F7C119F57E5AFE25B13E06BB669508542CE257DB955EE4BD8840830EE5C728A470EEC8E267BBCB113000F29C5E":
Check first that the signature matches.
> signature := convert(sigHex, decimal, hex):
> sigD := Power(signature,Sendere) mod Sendern;
> hashRecover := substring(convert(2^64+sigD,hex),2..17);
sigD := 15012940563366433863
hashRecover := D058ADE681825447
Next the receiver recovers the session key using the receiver's private key;
> encryptKey := convert(encryptKeyHex,decimal,hex):
> keyNum := Power(encryptKey, Receiverd) mod Receivern:
> sessionKey := substring(convert(keyNum + 2^64, hex),2..17);
sessionKey := 7778EEFFF432E596
Now the receiver starts decrypting the message with the standard procedure for CBC mode.
> key := keyexpander(sessionKey):
> allZeroes := substring(convert(2^64+0,hex),2..17):
> IV := qdDEShex(allZeroes,key);
IV := "04844CB2337C0CC2"
> messWords := linalg[vectdim](cipherList);
messWords := 73
> plainTable[1] := xor64hex(unDEShex(cipherList[1],key), IV):
> for i from 2 to messWords do
> plainTable[i] := xor64hex(unDEShex(cipherList[i],key), cipherList[i-1]);
> od:
> plainList := convert(plainTable,list);
plainList := [5468697320697320, 616E20617474656D, 707420746F206C6F,
6F6B206174206120, 726561736F6E6162, 6C65207761792074,
6F2073656E642061, 206D657373616765, "0D696E2073756368",
2061207761792074, 6861742069742069, 7320656E63727970,
7465642C20627574, 2074686174207468, 6520726563656976,
65722063616E2061, 6C736F2072657669, 667920746861740D,
746865206D657373, 6167652069732072, 65616C6C79206672,
6F6D206D652C2061, 6E64207468617420, 6E6F206F6E652068,
61732074616D7065, 7265642077697468, 2069742061667465,
7220490D7369676E, 656420746865206D, 6573736167652E20,
2054686572652061, 7265207365766572, 616C207069656365,
7320746F20646561, 6C20776974682E20, 2049206E65656420,
746F20686173680D, 746865206D657373, 61676520646F776E,
20746F2061206469, 67657374206F6620, 726561736F6E6162,
6C65206C656E6774, 682E202057652077, 696C6C20646F2074,
6861742077697468, 204445532E0D4166, 7465722077652068,
6176652061206861, 7368656420646967, 6573742C20776520,
7369676E20697420, 7769746820525341, 2E20205468656E2C,
2073696E63652049, 2077616E7420746F, 2068617665200D74,
6865206D65737361, 6765206465637279, 7074656420627920,
74686520696E7465, 6E64656420726563, 697069656E742061,
6C6F6E652C204920, 656E637279707420, 7468652073657373,
696F6E206B65790D, 7769746820525341, 20616E6420746865,
2072656365697665, 722773207075626C, 6963206B65792E20,
7800000000000000]
Finally we convert back to text,
> plainListBytes := map(x -> seq(convert(substring(x,2*i+1..2*i+2),decimal,hex),i=0..7),
> plainList):
> received := convert(plainListBytes,bytes);
received := "This is an attempt to look at a reasonable way to s\
end a message
in such a way that it is encrypted, but that\
the receiver can also revify that
the message is really f\
rom me, and that no one has tampered with it after I
signe\
d the message. There are several pieces to deal with. I \
need to hash
the message down to a digest of reasonable le\
ngth. We will do that with DES.
After we have a hashed di\
gest, we sign it with RSA. Then, since I want to have
th\
e message decrypted by the intended recipient alone, I enc\
rypt the session key
with RSA and the receiver's public ke\
y. x"
This becomes easier to read if it is converted from a string to a name.
> convert(received, name);
This is an attempt to look at a reasonable way to send a message\
in such a way that it is encrypted, but that the receiver\
can also revify that
the message is really from me, and t\
hat no one has tampered with it after I
signed the message\
. There are several pieces to deal with. I need to hash
\
the message down to a digest of reasonable length. We wil\
l do that with DES.
After we have a hashed digest, we sign\
it with RSA. Then, since I want to have
the message dec\
rypted by the intended recipient alone, I encrypt the sess\
ion key
with RSA and the receiver's public key. x
>
Exercises:
1) The following message was sent to to a receiver with the following private key:
Receivern := 1457907094342636571934108159685862980326515914911824861643397522980497550736230615496046802186876835611836753440525199587698019954839165932427842278373706998741;
Receiverd := 341802989220968474720655078407209434254191022363248073594317758527173121550607778293183240178522095499109087453784896094825475099226794560236481979918863102913;
Verify that it was sent by sender, decrypt it, formulate a reply to sender that is encrypted and signed.
Sendern := 2647133060482247855476731451635129223485131680531364416078202783345268194500738733550245848470594033764469895630694651936487340877088430911072869585934526325563:
Sendere := 65537:
cipherlist := ["841DF241571484DA", "79793834C7DD81D0", "48ABB98186432AE6", "81DBE80752EADAB6", "8B43C22E1099BC4E", "3319DDD18A5216D7", "2C465263FCB169D7", AD1DB4C8E76699AE, "9F439228B3264B02", "7D235364FC85B872", "2AEB9BBBB01BBE9A", "5BA93E6E539970B1", "8FC41AEE50B953FA", "324B23BB22CCD112", "395513EC6C5F82D1", D821C1549F0C8AC0, "58FE6D0F4F6C8643", "4B5C7E74B3859EFD", "9907A68B351101D3", "56424729A52A8889", "5D3AF3A93FD72238", DEE853E94A56B0BA, B0430A8817016724, "6D9FD3FFBB3A4D50", E81B5EE640F89D42, "510DFC71FA25C40C", "3CC43FBB5B655D72", "630071DB2D013E9F", "6B2286634C67C6DE", "58447F6CBD665E69", E945777C507A99CE, "0367FD0AC597D731", "616B270C7B713B66", "537B8E0728D3E8E9", E4C57177141001F5, A5F09AE750BE19FD, "55D5BEAC66E71FC5", "4E33D27B5A5F7E09", B9203D5C4EF0068D, "5DC41D5BA801444F", "8786352A029EE02D", "04B30B785A76F6DA", "623F4AB38026661B", "48BC5F2C834D1F35", F115C4747A0521E8, "936C3DA21AD0D3ED", AC52CC995163B0DF, E54536560E8CBA96, "157912D241792771", "29C096048813A485", CE70C7E14525124C, "2B7D0241F09A6890", "377D1B206D53823B", "1301320EF2E23257", "444DF372B826A9CF", FC580B4A75667C47, C310038925FB71DA, "85E21A5B46FDE69A", B328EC3944D128DE, "650D24EB4D657855", D6CF942B2CFF4805, "694BA546F05B9471", "5C0C7A9B814E4D87", C698D4BF4704ACFF, "2BF5C15310CB94BF", "3FF942653F528FB0", "7A0A0B17200F9BC7", "7B8C888CA6E7C992", "6FBE19BB8BB32031", "97C62DA7C96C134C", "8CC5430A980A3DDC", EF150D80FD6B277E, "2762FAAA92DA27C6", ABA7010CE599034D, "1DBB5EE17CAB5788", B769F09C13715FD2, "6D4AFC0B31B19123", D7671D4064D46B27, "9BC484AEE970D44A", "99DA4B18A0B9D70D", "512AA8D5AEBA0CBF"];
sigHex := "17E394C94FF7357CA2B856A764D54911A64F45000EA103E0BA0971FE35371AE81CC2AB9413FA808218C9049CC0AF7CFDD4DC04E4E600994A6BE02DDDA3221854DDC89";
encryptKeyHex := "120B390A6D5333E6D19BCC3FE367C27B3B5562F89344A2B1708307AF1593E956FE1D1EECE000AF9EC6DB69913119B2886B6207C7908966B6EFAA0D6BA868E0DA65584";
>
2) Create a 10 line message, a random DES key, and a pair of RSA keys, one for encryption and one for signing. Encrypt your message with DES is CBC mode, consider the last cipherword to be a has of the message and sign the hash. Encrypt your DES key with RSA and post the composite message to the bulletin board. (You will also need to append the receiver's private key on this problem.
>
3) Pull your own message off the bulletin board and decrypt it to be sure that it works.
>
4) Exchange public RSA keys with someone in the class. Send a message and reply using this secured mail system.
>
>
>