2
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation, either version 2 or (at your option)
7
* version 3 of the License.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18
#include "OpenSSHKeyGen.h"
19
#include "BinaryStream.h"
20
#include "OpenSSHKey.h"
21
#include "crypto/Random.h"
23
#include <botan/ecdsa.h>
24
#include <botan/ed25519.h>
27
namespace OpenSSHKeyGen
31
void bigIntToStream(const Botan::BigInt& i, BinaryStream& stream, int padding = 0)
33
QByteArray ba(i.bytes() + padding, 0);
34
i.binary_encode(reinterpret_cast<uint8_t*>(ba.data() + padding), ba.size() - padding);
35
stream.writeString(ba);
38
void vectorToStream(const std::vector<uint8_t>& v, BinaryStream& stream)
40
QByteArray ba(reinterpret_cast<const char*>(v.data()), v.size());
41
stream.writeString(ba);
44
void vectorToStream(const Botan::secure_vector<uint8_t>& v, BinaryStream& stream)
46
QByteArray ba(reinterpret_cast<const char*>(v.data()), v.size());
47
stream.writeString(ba);
51
bool generateRSA(OpenSSHKey& key, int bits)
53
auto rng = randomGen()->getRng();
56
Botan::RSA_PrivateKey rsaKey(*rng, bits);
58
QByteArray publicData;
59
BinaryStream publicStream(&publicData);
60
// intentionally flipped n e -> e n
61
bigIntToStream(rsaKey.get_e(), publicStream);
62
bigIntToStream(rsaKey.get_n(), publicStream, 1);
64
QByteArray privateData;
65
BinaryStream privateStream(&privateData);
66
bigIntToStream(rsaKey.get_n(), privateStream, 1);
67
bigIntToStream(rsaKey.get_e(), privateStream);
68
bigIntToStream(rsaKey.get_d(), privateStream, 1);
69
bigIntToStream(rsaKey.get_c(), privateStream, 1);
70
bigIntToStream(rsaKey.get_p(), privateStream, 1);
71
bigIntToStream(rsaKey.get_q(), privateStream, 1);
73
key.setType("ssh-rsa");
74
key.setCheck(randomGen()->randomUInt(std::numeric_limits<quint32>::max() - 1) + 1);
75
key.setPublicData(publicData);
76
key.setPrivateData(privateData);
77
key.setComment("id_rsa");
79
} catch (std::exception& e) {
84
bool generateECDSA(OpenSSHKey& key, int bits)
86
auto rng = randomGen()->getRng();
87
QString group = QString("nistp%1").arg(bits);
90
Botan::EC_Group domain(QString("secp%1r1").arg(bits).toStdString());
91
Botan::ECDSA_PrivateKey ecdsaKey(*rng, domain);
93
QByteArray publicData;
94
BinaryStream publicStream(&publicData);
95
publicStream.writeString(group);
96
vectorToStream(ecdsaKey.public_key_bits(), publicStream);
98
QByteArray privateData;
99
BinaryStream privateStream(&privateData);
100
privateStream.writeString(group);
101
vectorToStream(ecdsaKey.public_key_bits(), privateStream);
102
bigIntToStream(ecdsaKey.private_value(), privateStream, 1);
104
key.setType("ecdsa-sha2-" + group);
105
key.setCheck(randomGen()->randomUInt(std::numeric_limits<quint32>::max() - 1) + 1);
106
key.setPublicData(publicData);
107
key.setPrivateData(privateData);
108
key.setComment("id_ecdsa");
110
} catch (std::exception& e) {
115
bool generateEd25519(OpenSSHKey& key)
117
auto rng = randomGen()->getRng();
120
Botan::Ed25519_PrivateKey ed25519Key(*rng);
122
QByteArray publicData;
123
BinaryStream publicStream(&publicData);
124
vectorToStream(ed25519Key.get_public_key(), publicStream);
126
QByteArray privateData;
127
BinaryStream privateStream(&privateData);
128
vectorToStream(ed25519Key.get_public_key(), privateStream);
129
vectorToStream(ed25519Key.get_private_key(), privateStream);
131
key.setType("ssh-ed25519");
132
key.setCheck(randomGen()->randomUInt(std::numeric_limits<quint32>::max() - 1) + 1);
133
key.setPublicData(publicData);
134
key.setPrivateData(privateData);
135
key.setComment("id_ed25519");
137
} catch (std::exception& e) {
141
} // namespace OpenSSHKeyGen