1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE examples.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    The code included in this file is provided under the terms of the ISC license
8    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
9    To use, copy, modify, and/or distribute this software for any purpose with or
10    without fee is hereby granted provided that the above copyright notice and
11    this permission notice appear in all copies.
12 
13    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
14    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
15    PURPOSE, ARE DISCLAIMED.
16 
17   ==============================================================================
18 */
19 
20 /*******************************************************************************
21  The block below describes the properties of this PIP. A PIP is a short snippet
22  of code that can be read by the Projucer and used to generate a JUCE project.
23 
24  BEGIN_JUCE_PIP_METADATA
25 
26  name:             CryptographyDemo
27  version:          1.0.0
28  vendor:           JUCE
29  website:          http://juce.com
30  description:      Encrypts and decrypts data.
31 
32  dependencies:     juce_core, juce_cryptography, juce_data_structures, juce_events,
33                    juce_graphics, juce_gui_basics
34  exporters:        xcode_mac, vs2019, linux_make, androidstudio, xcode_iphone
35 
36  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1
37 
38  type:             Component
39  mainClass:        CryptographyDemo
40 
41  useLocalCopy:     1
42 
43  END_JUCE_PIP_METADATA
44 
45 *******************************************************************************/
46 
47 #pragma once
48 
49 #include "../Assets/DemoUtilities.h"
50 
51 //==============================================================================
52 class RSAComponent  : public Component
53 {
54 public:
RSAComponent()55     RSAComponent()
56     {
57         addAndMakeVisible (rsaGroup);
58 
59         addAndMakeVisible (bitSize);
60         bitSize.setText (String (256));
61         bitSizeLabel.attachToComponent (&bitSize, true);
62 
63         addAndMakeVisible (generateRSAButton);
64         generateRSAButton.onClick = [this] { createRSAKey(); };
65 
66         addAndMakeVisible (rsaResultBox);
67         rsaResultBox.setReadOnly (true);
68         rsaResultBox.setMultiLine (true);
69     }
70 
resized()71     void resized() override
72     {
73         auto area = getLocalBounds();
74         rsaGroup.setBounds (area);
75         area.removeFromTop (10);
76         area.reduce (5, 5);
77 
78         auto topArea = area.removeFromTop (34);
79         topArea.removeFromLeft (110);
80         bitSize.setBounds (topArea.removeFromLeft (topArea.getWidth() / 2).reduced (5));
81         generateRSAButton.setBounds (topArea.reduced (5));
82 
83         rsaResultBox.setBounds (area.reduced (5));
84     }
85 
86 private:
createRSAKey()87     void createRSAKey()
88     {
89         auto bits = jlimit (32, 1024, bitSize.getText().getIntValue());
90         bitSize.setText (String (bits), dontSendNotification);
91 
92         // Create a key-pair...
93         RSAKey publicKey, privateKey;
94         RSAKey::createKeyPair (publicKey, privateKey, bits);
95 
96         // Test the new key on a piece of data...
97         BigInteger testValue;
98         testValue.parseString ("1234567890abcdef", 16);
99 
100         auto encodedValue = testValue;
101         publicKey.applyToValue (encodedValue);
102 
103         auto decodedValue = encodedValue;
104         privateKey.applyToValue (decodedValue);
105 
106         // ..and show the results..
107         String message;
108         message << "Number of bits: " << bits << newLine
109                 << "Public Key: "  << publicKey .toString() << newLine
110                 << "Private Key: " << privateKey.toString() << newLine
111                 << newLine
112                 << "Test input: " << testValue.toString (16) << newLine
113                 << "Encoded: " << encodedValue.toString (16) << newLine
114                 << "Decoded: " << decodedValue.toString (16) << newLine;
115 
116         rsaResultBox.setText (message, false);
117     }
118 
119     GroupComponent rsaGroup       { {}, "RSA Encryption" };
120     TextButton generateRSAButton  { "Generate RSA" };
121     Label bitSizeLabel            { {}, "Num Bits to Use:" };
122     TextEditor bitSize, rsaResultBox;
123 
lookAndFeelChanged()124     void lookAndFeelChanged() override
125     {
126         rsaGroup.setColour (GroupComponent::outlineColourId,
127                             getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::outline,
128                                                     Colours::grey));
129         rsaGroup.setColour (GroupComponent::textColourId,
130                             getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::defaultText,
131                                                     Colours::white));
132         rsaResultBox.setColour (TextEditor::backgroundColourId,
133                                 getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::widgetBackground,
134                                                         Colours::white.withAlpha (0.5f)));
135 
136         bitSize.applyFontToAllText (bitSize.getFont());
137         rsaResultBox.applyFontToAllText (rsaResultBox.getFont());
138     }
139 
140     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RSAComponent)
141 };
142 
143 //==============================================================================
144 class HashesComponent  : public Component
145 {
146 public:
HashesComponent()147     HashesComponent()
148     {
149         addAndMakeVisible (hashGroup);
150 
151         addAndMakeVisible (hashEntryBox);
152         hashEntryBox.setMultiLine (true);
153 
154         hashEntryBox.setReturnKeyStartsNewLine (true);
155         hashEntryBox.setText ("Type some text in this box and the resulting MD5, SHA and Whirlpool hashes will update below");
156 
157         auto updateHashes = [this]
158         {
159             auto text = hashEntryBox.getText();
160 
161             updateMD5Result       (text.toUTF8());
162             updateSHA256Result    (text.toUTF8());
163             updateWhirlpoolResult (text.toUTF8());
164         };
165 
166         hashEntryBox.onTextChange = updateHashes;
167         hashEntryBox.onReturnKey  = updateHashes;
168 
169         hashLabel1.attachToComponent (&hashEntryBox,    true);
170         hashLabel2.attachToComponent (&md5Result,       true);
171         hashLabel3.attachToComponent (&shaResult,       true);
172         hashLabel4.attachToComponent (&whirlpoolResult, true);
173 
174         addAndMakeVisible (md5Result);
175         addAndMakeVisible (shaResult);
176         addAndMakeVisible (whirlpoolResult);
177 
178         updateHashes();
179     }
180 
updateMD5Result(CharPointer_UTF8 text)181     void updateMD5Result (CharPointer_UTF8 text)
182     {
183         md5Result.setText (MD5 (text).toHexString(), dontSendNotification);
184     }
185 
updateSHA256Result(CharPointer_UTF8 text)186     void updateSHA256Result (CharPointer_UTF8 text)
187     {
188         shaResult.setText (SHA256 (text).toHexString(), dontSendNotification);
189     }
190 
updateWhirlpoolResult(CharPointer_UTF8 text)191     void updateWhirlpoolResult (CharPointer_UTF8 text)
192     {
193         whirlpoolResult.setText (Whirlpool (text).toHexString(), dontSendNotification);
194     }
195 
resized()196     void resized() override
197     {
198         auto area = getLocalBounds();
199 
200         hashGroup.setBounds (area);
201 
202         area.removeFromLeft (120);
203         area.removeFromTop (10);
204         area.reduce (5, 5);
205 
206         whirlpoolResult.setBounds (area.removeFromBottom (34));
207         shaResult      .setBounds (area.removeFromBottom (34));
208         md5Result      .setBounds (area.removeFromBottom (34));
209         hashEntryBox   .setBounds (area.reduced (5));
210     }
211 
212 private:
213     GroupComponent hashGroup { {}, "Hashes" };
214     TextEditor hashEntryBox;
215     Label md5Result, shaResult, whirlpoolResult;
216 
217     Label hashLabel1  { {}, "Text to Hash:" };
218     Label hashLabel2  { {}, "MD5 Result:" };
219     Label hashLabel3  { {}, "SHA Result:" };
220     Label hashLabel4  { {}, "Whirlpool Result:" };
221 
lookAndFeelChanged()222     void lookAndFeelChanged() override
223     {
224         hashGroup.setColour (GroupComponent::outlineColourId,
225                              getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::outline,
226                                                      Colours::grey));
227         hashGroup.setColour (GroupComponent::textColourId,
228                              getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::defaultText,
229                                                      Colours::white));
230         hashEntryBox.setColour (TextEditor::backgroundColourId,
231                                 getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::widgetBackground,
232                                                         Colours::white.withAlpha (0.5f)));
233 
234         hashEntryBox.applyFontToAllText (hashEntryBox.getFont());
235     }
236 
237     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HashesComponent)
238 };
239 
240 //==============================================================================
241 class CryptographyDemo  : public Component
242 {
243 public:
CryptographyDemo()244     CryptographyDemo()
245     {
246         addAndMakeVisible (rsaDemo);
247         addAndMakeVisible (hashDemo);
248 
249         setSize (750, 750);
250     }
251 
paint(Graphics & g)252     void paint (Graphics& g) override
253     {
254         g.fillAll (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::windowBackground,
255                                            Colour::greyLevel (0.4f)));
256     }
257 
resized()258     void resized() override
259     {
260         auto area = getLocalBounds();
261 
262         rsaDemo .setBounds (area.removeFromTop (getHeight() / 2).reduced (5));
263         hashDemo.setBounds (area.reduced (5));
264     }
265 
266 private:
267     RSAComponent rsaDemo;
268     HashesComponent hashDemo;
269 
270     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CryptographyDemo)
271 };
272