Skip to content

Commit 27902c7

Browse files
author
Gonçalo Montes Palma
committed
Added UI and commented code
1 parent e5674f0 commit 27902c7

File tree

7 files changed

+527
-145
lines changed

7 files changed

+527
-145
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>BuildSystemType</key>
6+
<string>Original</string>
7+
</dict>
8+
</plist>

lib/main.dart

Lines changed: 11 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import 'package:flutter/material.dart';
2-
3-
void main() => runApp(MyApp());
2+
import 'package:rsa_key_generator/ui/home_page.dart';
3+
import 'package:rsa_key_generator/utils/dependency_provider.dart';
4+
5+
void main() {
6+
// We need to encapsulate `MyApp` with the DependencyProvider in order
7+
// to be able to access the RSA KeyHelper
8+
runApp(
9+
DependencyProvider(child: MyApp(),)
10+
);
11+
}
412

513
class MyApp extends StatelessWidget {
614
// This widget is the root of your application.
@@ -9,103 +17,9 @@ class MyApp extends StatelessWidget {
917
return MaterialApp(
1018
title: 'Flutter Demo',
1119
theme: ThemeData(
12-
// This is the theme of your application.
13-
//
14-
// Try running your application with "flutter run". You'll see the
15-
// application has a blue toolbar. Then, without quitting the app, try
16-
// changing the primarySwatch below to Colors.green and then invoke
17-
// "hot reload" (press "r" in the console where you ran "flutter run",
18-
// or simply save your changes to "hot reload" in a Flutter IDE).
19-
// Notice that the counter didn't reset back to zero; the application
20-
// is not restarted.
2120
primarySwatch: Colors.blue,
2221
),
23-
home: MyHomePage(title: 'Flutter Demo Home Page'),
24-
);
25-
}
26-
}
27-
28-
class MyHomePage extends StatefulWidget {
29-
MyHomePage({Key key, this.title}) : super(key: key);
30-
31-
// This widget is the home page of your application. It is stateful, meaning
32-
// that it has a State object (defined below) that contains fields that affect
33-
// how it looks.
34-
35-
// This class is the configuration for the state. It holds the values (in this
36-
// case the title) provided by the parent (in this case the App widget) and
37-
// used by the build method of the State. Fields in a Widget subclass are
38-
// always marked "final".
39-
40-
final String title;
41-
42-
@override
43-
_MyHomePageState createState() => _MyHomePageState();
44-
}
45-
46-
class _MyHomePageState extends State<MyHomePage> {
47-
int _counter = 0;
48-
49-
void _incrementCounter() {
50-
setState(() {
51-
// This call to setState tells the Flutter framework that something has
52-
// changed in this State, which causes it to rerun the build method below
53-
// so that the display can reflect the updated values. If we changed
54-
// _counter without calling setState(), then the build method would not be
55-
// called again, and so nothing would appear to happen.
56-
_counter++;
57-
});
58-
}
59-
60-
@override
61-
Widget build(BuildContext context) {
62-
// This method is rerun every time setState is called, for instance as done
63-
// by the _incrementCounter method above.
64-
//
65-
// The Flutter framework has been optimized to make rerunning build methods
66-
// fast, so that you can just rebuild anything that needs updating rather
67-
// than having to individually change instances of widgets.
68-
return Scaffold(
69-
appBar: AppBar(
70-
// Here we take the value from the MyHomePage object that was created by
71-
// the App.build method, and use it to set our appbar title.
72-
title: Text(widget.title),
73-
),
74-
body: Center(
75-
// Center is a layout widget. It takes a single child and positions it
76-
// in the middle of the parent.
77-
child: Column(
78-
// Column is also layout widget. It takes a list of children and
79-
// arranges them vertically. By default, it sizes itself to fit its
80-
// children horizontally, and tries to be as tall as its parent.
81-
//
82-
// Invoke "debug painting" (press "p" in the console, choose the
83-
// "Toggle Debug Paint" action from the Flutter Inspector in Android
84-
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
85-
// to see the wireframe for each widget.
86-
//
87-
// Column has various properties to control how it sizes itself and
88-
// how it positions its children. Here we use mainAxisAlignment to
89-
// center the children vertically; the main axis here is the vertical
90-
// axis because Columns are vertical (the cross axis would be
91-
// horizontal).
92-
mainAxisAlignment: MainAxisAlignment.center,
93-
children: <Widget>[
94-
Text(
95-
'You have pushed the button this many times:',
96-
),
97-
Text(
98-
'$_counter',
99-
style: Theme.of(context).textTheme.display1,
100-
),
101-
],
102-
),
103-
),
104-
floatingActionButton: FloatingActionButton(
105-
onPressed: _incrementCounter,
106-
tooltip: 'Increment',
107-
child: Icon(Icons.add),
108-
), // This trailing comma makes auto-formatting nicer for build methods.
22+
home: MyHomePage(title: 'RSA Key Generator'),
10923
);
11024
}
11125
}

lib/ui/home_page.dart

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter/services.dart';
3+
import 'package:pointycastle/api.dart' as crypto;
4+
import 'package:rsa_key_generator/utils/dependency_provider.dart';
5+
6+
TextStyle get whiteTextStyle => TextStyle(color: Colors.white);
7+
8+
class MyHomePage extends StatefulWidget {
9+
MyHomePage({Key key, this.title}) : super(key: key);
10+
final String title;
11+
12+
@override
13+
_MyHomePageState createState() => _MyHomePageState();
14+
}
15+
16+
class _MyHomePageState extends State<MyHomePage> {
17+
/// The Future that will show the Pem String
18+
Future<String> futurePemKey;
19+
20+
/// Future to hold the reference to the KeyPair generated with PointyCastle
21+
/// in order to extract the [crypto.PrivateKey] and [crypto.PublicKey]
22+
Future<crypto.AsymmetricKeyPair<crypto.PublicKey, crypto.PrivateKey>>
23+
futureKeyPair;
24+
25+
/// The current [crypto.AsymmetricKeyPair]
26+
crypto.AsymmetricKeyPair keyPair;
27+
28+
/// With the helper [RsaKeyHelper] this method generates a
29+
/// new [crypto.AsymmetricKeyPair<crypto.PublicKey, crypto.PrivateKey>
30+
Future<crypto.AsymmetricKeyPair<crypto.PublicKey, crypto.PrivateKey>>
31+
getKeyPair() {
32+
var keyHelper = DependencyProvider.of(context).getRsaKeyHelper();
33+
return keyHelper.getRSAKeyPair(keyHelper.getSecureRandom());
34+
}
35+
36+
/// GlobalKey to be used when showing the [Snackbar] for the successful
37+
/// copy of the Key
38+
final key = new GlobalKey<ScaffoldState>();
39+
40+
@override
41+
Widget build(BuildContext context) {
42+
return Scaffold(
43+
key: key,
44+
appBar: AppBar(
45+
title: Text(widget.title),
46+
),
47+
body: Center(
48+
child: Padding(
49+
padding: const EdgeInsets.all(8.0),
50+
child: Column(
51+
crossAxisAlignment: CrossAxisAlignment.stretch,
52+
children: <Widget>[
53+
MaterialButton(
54+
color: Theme.of(context).accentColor,
55+
child: Text(
56+
"Generate new Key Pair",
57+
style: whiteTextStyle,
58+
),
59+
onPressed: () {
60+
setState(() {
61+
// If there are any pemString being shown, then show an empty message
62+
futurePemKey = Future.value("");
63+
// Generate a new keypair
64+
futureKeyPair = getKeyPair();
65+
});
66+
},
67+
),
68+
Expanded(
69+
flex: 1,
70+
child: FutureBuilder<
71+
crypto.AsymmetricKeyPair<crypto.PublicKey,
72+
crypto.PrivateKey>>(
73+
future: futureKeyPair,
74+
builder: (context, snapshot) {
75+
if (snapshot.connectionState == ConnectionState.waiting) {
76+
// if we are waiting for a future to be completed, show a progress indicator
77+
return Center(child: CircularProgressIndicator());
78+
} else if (snapshot.hasData) {
79+
// Else, store the new keypair in this state and sbow two buttons
80+
this.keyPair = snapshot.data;
81+
return Column(
82+
crossAxisAlignment: CrossAxisAlignment.stretch,
83+
children: <Widget>[
84+
MaterialButton(
85+
color: Colors.red,
86+
child: Text("Get Private Key",
87+
style: whiteTextStyle),
88+
onPressed: () {
89+
setState(() {
90+
// With the stored keypair, encode the private key to
91+
// PKCS1 and show it
92+
futurePemKey = Future.value(
93+
DependencyProvider.of(context)
94+
.getRsaKeyHelper()
95+
.encodePrivateKeyToPemPKCS1(
96+
keyPair.privateKey));
97+
});
98+
},
99+
),
100+
MaterialButton(
101+
color: Colors.green,
102+
child:
103+
Text("Get Public Key", style: whiteTextStyle),
104+
onPressed: () {
105+
setState(() {
106+
// With the stored keypair, encode the public key to
107+
// PKCS1 and show it
108+
futurePemKey = Future.value(
109+
DependencyProvider.of(context)
110+
.getRsaKeyHelper()
111+
.encodePublicKeyToPemPKCS1(
112+
keyPair.publicKey));
113+
});
114+
},
115+
)
116+
],
117+
);
118+
} else {
119+
return Container(
120+
color: Colors.red,
121+
);
122+
}
123+
}),
124+
),
125+
Expanded(
126+
flex: 3,
127+
child: FutureBuilder(
128+
future: futurePemKey,
129+
builder: (context, snapshot) {
130+
if (snapshot.hasData) {
131+
return Card(
132+
child: Container(
133+
padding: EdgeInsets.all(8),
134+
margin: EdgeInsets.all(8),
135+
child: SingleChildScrollView(
136+
// the inkwell is used to register the taps
137+
// in order to be able to copy the text
138+
child: InkWell(
139+
onTap: () {
140+
// Copies the data to the keyboard
141+
Clipboard.setData(
142+
new ClipboardData(text: snapshot.data));
143+
key.currentState.showSnackBar(new SnackBar(
144+
content: new Text("Copied to Clipboard"),
145+
));
146+
},
147+
child: Text(snapshot.data)),
148+
),
149+
),
150+
);
151+
} else {
152+
return Center(
153+
child: Text("Your keys will appear here"),
154+
);
155+
}
156+
}),
157+
)
158+
],
159+
),
160+
),
161+
),
162+
);
163+
}
164+
}

lib/utils/dependency_provider.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:rsa_key_generator/utils/rsa_key_helper.dart';
3+
4+
/// As an [InheritedWidget] this class will provide its childs the objects it hold
5+
///
6+
/// By accessing [of] and providing a [BuildContext] we can access, for example, the [Config] instance.
7+
/// Usage: `var provider = DependencyProvider.of(context);`
8+
class DependencyProvider extends InheritedWidget {
9+
10+
static DependencyProvider of(BuildContext context) {
11+
return (context.inheritFromWidgetOfExactType(DependencyProvider)
12+
as DependencyProvider);
13+
}
14+
15+
DependencyProvider({
16+
Key key,
17+
Widget child,
18+
}) : super(key: key, child: child);
19+
20+
@override
21+
bool updateShouldNotify(InheritedWidget oldWidget) => false;
22+
23+
RsaKeyHelper getRsaKeyHelper() {
24+
return RsaKeyHelper();
25+
}
26+
}

0 commit comments

Comments
 (0)