Skip to content

Commit e3b2e83

Browse files
Android: replace KeyPairGeneratorSpec with KeyGenParameterSpec
Replace deprecated android.security.KeyPairGeneratorSpec usage with android.security.keystore.KeyGenParameterSpec (API 23+). Implemented with the help of Github Copilot (Claude Sonnet 4.6)
1 parent 98ffa3a commit e3b2e83

3 files changed

Lines changed: 47 additions & 191 deletions

File tree

qtkeychain/androidkeystore.cpp

Lines changed: 27 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,15 @@
1010

1111
using namespace QKeychain;
1212

13-
using namespace android::content;
14-
using namespace android::security;
15-
1613
using namespace java::io;
1714
using namespace java::lang;
18-
using namespace java::math;
19-
using namespace java::util;
2015
using namespace java::security;
2116
using namespace java::security::spec;
2217

2318
using namespace javax::crypto;
24-
using namespace javax::security::auth::x500;
2519
using namespace javax::security::cert;
2620

27-
const BigInteger BigInteger::ONE =
28-
BigInteger::getStaticObjectField("java/math/BigInteger", "ONE", "Ljava/math/BigInteger;");
29-
30-
const int Calendar::YEAR = Calendar::getStaticField<jint>("java/util/Calendar", "YEAR");
21+
using namespace android::security::keystore;
3122

3223
const int Cipher::DECRYPT_MODE =
3324
Cipher::getStaticField<jint>("javax/crypto/Cipher", "DECRYPT_MODE");
@@ -146,79 +137,44 @@ bool KeyStore::load(const KeyStore::LoadStoreParameter &param) const
146137
return handleExceptions();
147138
}
148139

149-
Calendar Calendar::getInstance()
150-
{
151-
return handleExceptions(
152-
callStaticObjectMethod("java/util/Calendar", "getInstance", "()Ljava/util/Calendar;"));
153-
}
154-
155-
bool Calendar::add(int field, int amount) const
156-
{
157-
callMethod<void>("add", "(II)V", field, amount);
158-
return handleExceptions();
159-
}
160-
161-
Date Calendar::getTime() const
162-
{
163-
return handleExceptions(callObjectMethod("getTime", "()Ljava/util/Date;"));
164-
}
165-
166-
KeyPairGeneratorSpec::Builder::Builder(const Context &context)
167-
: Object(QAndroidJniObject("android/security/KeyPairGeneratorSpec$Builder",
168-
"(Landroid/content/Context;)V", context.object()))
140+
KeyGenParameterSpec::Builder::Builder(const QString &keystoreAlias, int purposes)
141+
: Object(QAndroidJniObject("android/security/keystore/KeyGenParameterSpec$Builder",
142+
"(Ljava/lang/String;I)V",
143+
fromString(keystoreAlias).object(),
144+
static_cast<jint>(purposes)))
169145
{
170146
handleExceptions();
171147
}
172148

173-
KeyPairGeneratorSpec::Builder KeyPairGeneratorSpec::Builder::setAlias(const QString &alias) const
174-
{
175-
return handleExceptions(callObjectMethod(
176-
"setAlias", "(Ljava/lang/String;)Landroid/security/KeyPairGeneratorSpec$Builder;",
177-
fromString(alias).object()));
178-
}
179-
180-
KeyPairGeneratorSpec::Builder
181-
KeyPairGeneratorSpec::Builder::setSubject(const X500Principal &subject) const
182-
{
183-
return handleExceptions(callObjectMethod("setSubject",
184-
"(Ljavax/security/auth/x500/X500Principal;)Landroid/"
185-
"security/KeyPairGeneratorSpec$Builder;",
186-
subject.object()));
187-
}
188-
189-
KeyPairGeneratorSpec::Builder
190-
KeyPairGeneratorSpec::Builder::setSerialNumber(const BigInteger &serial) const
191-
{
192-
return handleExceptions(callObjectMethod(
193-
"setSerialNumber",
194-
"(Ljava/math/BigInteger;)Landroid/security/KeyPairGeneratorSpec$Builder;",
195-
serial.object()));
196-
}
197-
198-
KeyPairGeneratorSpec::Builder KeyPairGeneratorSpec::Builder::setStartDate(const Date &date) const
149+
KeyGenParameterSpec::Builder
150+
KeyGenParameterSpec::Builder::setEncryptionPadding(const QString &padding) const
199151
{
200-
return handleExceptions(callObjectMethod(
201-
"setStartDate", "(Ljava/util/Date;)Landroid/security/KeyPairGeneratorSpec$Builder;",
202-
date.object()));
152+
QAndroidJniEnvironment env;
153+
const jclass stringClass = env->FindClass("java/lang/String");
154+
const jobjectArray arr = env->NewObjectArray(1, stringClass, nullptr);
155+
env->DeleteLocalRef(stringClass);
156+
const QAndroidJniObject str = fromString(padding);
157+
env->SetObjectArrayElement(arr, 0, str.object());
158+
const KeyGenParameterSpec::Builder result = handleExceptions(callObjectMethod(
159+
"setEncryptionPaddings",
160+
"([Ljava/lang/String;)Landroid/security/keystore/KeyGenParameterSpec$Builder;",
161+
arr));
162+
env->DeleteLocalRef(arr);
163+
return result;
203164
}
204165

205-
KeyPairGeneratorSpec::Builder KeyPairGeneratorSpec::Builder::setEndDate(const Date &date) const
166+
KeyGenParameterSpec::Builder KeyGenParameterSpec::Builder::setKeySize(int keySize) const
206167
{
207168
return handleExceptions(callObjectMethod(
208-
"setEndDate", "(Ljava/util/Date;)Landroid/security/KeyPairGeneratorSpec$Builder;",
209-
date.object()));
210-
}
211-
212-
KeyPairGeneratorSpec KeyPairGeneratorSpec::Builder::build() const
213-
{
214-
return handleExceptions(callObjectMethod("build", "()Landroid/security/KeyPairGeneratorSpec;"));
169+
"setKeySize",
170+
"(I)Landroid/security/keystore/KeyGenParameterSpec$Builder;",
171+
static_cast<jint>(keySize)));
215172
}
216173

217-
X500Principal::X500Principal(const QString &name)
218-
: Object(QAndroidJniObject("javax/security/auth/x500/X500Principal", "(Ljava/lang/String;)V",
219-
fromString(name).object()))
174+
KeyGenParameterSpec KeyGenParameterSpec::Builder::build() const
220175
{
221-
handleExceptions();
176+
return handleExceptions(
177+
callObjectMethod("build", "()Landroid/security/keystore/KeyGenParameterSpec;"));
222178
}
223179

224180
Certificate KeyStore::PrivateKeyEntry::getCertificate() const

qtkeychain/androidkeystore_p.h

Lines changed: 12 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,9 @@ namespace QKeychain {
2727

2828
namespace javax {
2929
namespace security {
30-
31-
namespace auth {
32-
namespace x500 {
33-
class X500Principal;
34-
}
35-
} // namespace auth
3630
namespace cert {
3731
class Certificate;
3832
}
39-
4033
} // namespace security
4134
} // namespace javax
4235

@@ -124,49 +117,6 @@ class FilterOutputStream : public OutputStream
124117

125118
} // namespace io
126119

127-
namespace math {
128-
129-
class BigInteger : public java::lang::Object
130-
{
131-
public:
132-
using Object::Object;
133-
134-
static const BigInteger ZERO;
135-
static const BigInteger ONE;
136-
static const BigInteger TEN;
137-
};
138-
139-
} // namespace math
140-
141-
namespace util {
142-
143-
class Date : public java::lang::Object
144-
{
145-
public:
146-
using Object::Object;
147-
};
148-
149-
class Calendar : public java::lang::Object
150-
{
151-
public:
152-
using Object::Object;
153-
154-
static const int YEAR;
155-
static const int MONTH;
156-
static const int DAY;
157-
static const int HOUR;
158-
static const int MINUTE;
159-
static const int SECOND;
160-
static const int MILLISECOND;
161-
162-
static Calendar getInstance();
163-
164-
bool add(int field, int amount) const;
165-
Date getTime() const;
166-
};
167-
168-
} // namespace util
169-
170120
namespace security {
171121
namespace spec {
172122

@@ -288,39 +238,33 @@ class RSAPublicKey : public PublicKey
288238
} // namespace java
289239

290240
namespace android {
291-
namespace content {
292-
293-
class Context : public java::lang::Object
294-
{
295-
public:
296-
using Object::Object;
297-
};
298-
299-
} // namespace content
300-
301241
namespace security {
242+
namespace keystore {
302243

303-
class KeyPairGeneratorSpec : public java::security::spec::AlgorithmParameterSpec
244+
namespace KeyProperties {
245+
static const int PURPOSE_ENCRYPT = 1;
246+
static const int PURPOSE_DECRYPT = 2;
247+
} // namespace KeyProperties
248+
249+
class KeyGenParameterSpec : public java::security::spec::AlgorithmParameterSpec
304250
{
305251
public:
306252
class Builder : public java::lang::Object
307253
{
308254
public:
309255
using Object::Object;
310256

311-
explicit Builder(const android::content::Context &context);
257+
explicit Builder(const QString &keystoreAlias, int purposes);
312258

313-
Builder setAlias(const QString &alias) const;
314-
Builder setSubject(const javax::security::auth::x500::X500Principal &subject) const;
315-
Builder setSerialNumber(const java::math::BigInteger &serial) const;
316-
Builder setStartDate(const java::util::Date &date) const;
317-
Builder setEndDate(const java::util::Date &date) const;
318-
KeyPairGeneratorSpec build() const;
259+
Builder setEncryptionPadding(const QString &padding) const;
260+
Builder setKeySize(int keySize) const;
261+
KeyGenParameterSpec build() const;
319262
};
320263

321264
using AlgorithmParameterSpec::AlgorithmParameterSpec;
322265
};
323266

267+
} // namespace keystore
324268
} // namespace security
325269
} // namespace android
326270

@@ -378,22 +322,6 @@ class CipherOutputStream : public java::io::FilterOutputStream
378322
} // namespace crypto
379323

380324
namespace security {
381-
namespace auth {
382-
namespace x500 {
383-
384-
class X500Principal;
385-
386-
class X500Principal : public java::lang::Object
387-
{
388-
public:
389-
using Object::Object;
390-
391-
explicit X500Principal(const QString &name);
392-
};
393-
394-
} // namespace x500
395-
} // namespace auth
396-
397325
namespace cert {
398326

399327
class Certificate : public java::lang::Object

qtkeychain/keychain_android.cpp

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,21 @@
1212
#include "androidkeystore_p.h"
1313
#include "plaintextstore_p.h"
1414

15-
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
16-
# include <QtAndroid>
17-
#endif
18-
1915
using namespace QKeychain;
2016

21-
using android::content::Context;
22-
using android::security::KeyPairGeneratorSpec;
17+
using android::security::keystore::KeyGenParameterSpec;
2318

2419
using java::io::ByteArrayInputStream;
2520
using java::security::SecureRandom;
2621
using java::security::KeyPair;
2722
using java::security::KeyPairGenerator;
2823
using java::security::KeyStore;
29-
using java::security::interfaces::RSAPrivateKey;
3024
using java::security::interfaces::RSAPublicKey;
31-
using java::util::Calendar;
3225

3326
using javax::crypto::Cipher;
3427
using javax::crypto::CipherInputStream;
3528
using javax::crypto::GCMParameterSpec;
3629
using javax::crypto::SecretKeySpec;
37-
using javax::security::auth::x500::X500Principal;
3830

3931
namespace {
4032

@@ -165,33 +157,13 @@ void WritePasswordJobPrivate::scheduledStart()
165157

166158
const auto &alias = makeAlias(q->service(), q->key());
167159
if (!keyStore.containsAlias(alias)) {
168-
const auto start = Calendar::getInstance();
169-
const auto end = Calendar::getInstance();
170-
end.add(Calendar::YEAR, 99);
171-
172-
const KeyPairGeneratorSpec spec =
173-
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
174-
KeyPairGeneratorSpec::Builder(Context(QtAndroid::androidActivity()))
175-
.
176-
#elif QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
177-
KeyPairGeneratorSpec::Builder(
178-
Context(QNativeInterface::QAndroidApplication::context()))
179-
.
180-
#elif QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
181-
KeyPairGeneratorSpec::Builder(
182-
Context((jobject)QNativeInterface::QAndroidApplication::context()))
183-
.
184-
#else
185-
KeyPairGeneratorSpec::Builder(
186-
Context(QNativeInterface::QAndroidApplication::context().object<jobject>()))
187-
.
188-
#endif
189-
setAlias(alias)
190-
.setSubject(
191-
X500Principal(QStringLiteral("CN=QtKeychain, O=Android Authority")))
192-
.setSerialNumber(java::math::BigInteger::ONE)
193-
.setStartDate(start.getTime())
194-
.setEndDate(end.getTime())
160+
const KeyGenParameterSpec spec =
161+
KeyGenParameterSpec::Builder(
162+
alias,
163+
android::security::keystore::KeyProperties::PURPOSE_ENCRYPT
164+
| android::security::keystore::KeyProperties::PURPOSE_DECRYPT)
165+
.setEncryptionPadding(QStringLiteral("PKCS1Padding"))
166+
.setKeySize(2048)
195167
.build();
196168

197169
const auto generator = KeyPairGenerator::getInstance(QStringLiteral("RSA"),

0 commit comments

Comments
 (0)