Skip to content

Commit 867fb66

Browse files
jkmasselclaude
andcommitted
Fix rustfmt, clippy, and detekt lint errors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8dd177b commit 867fb66

File tree

2 files changed

+64
-34
lines changed

2 files changed

+64
-34
lines changed

native/kotlin/api/android/src/main/kotlin/rs/wordpress/api/android/KeystorePasswordTransformer.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import android.security.keystore.KeyInfo
66
import android.security.keystore.KeyProperties
77
import android.security.keystore.StrongBoxUnavailableException
88
import android.util.Base64
9+
import uniffi.wp_mobile.PasswordTransformer
10+
import uniffi.wp_mobile.PasswordTransformerException
911
import java.security.KeyStore
1012
import javax.crypto.Cipher
1113
import javax.crypto.KeyGenerator
1214
import javax.crypto.SecretKey
1315
import javax.crypto.SecretKeyFactory
1416
import javax.crypto.spec.GCMParameterSpec
15-
import uniffi.wp_mobile.PasswordTransformer
16-
import uniffi.wp_mobile.PasswordTransformerException
1717

1818
/**
1919
* A [PasswordTransformer] implementation that uses the Android Keystore for
@@ -77,6 +77,7 @@ class KeystorePasswordTransformer(alias: String = DEFAULT_ALIAS) : PasswordTrans
7777
}
7878
}
7979

80+
@Suppress("TooGenericExceptionCaught")
8081
override fun encrypt(password: String): String {
8182
try {
8283
val cipher = Cipher.getInstance(TRANSFORMATION)
@@ -91,17 +92,18 @@ class KeystorePasswordTransformer(alias: String = DEFAULT_ALIAS) : PasswordTrans
9192

9293
return Base64.encodeToString(combined, Base64.NO_WRAP)
9394
} catch (e: Exception) {
94-
throw PasswordTransformerException.EncryptionFailed(e.message ?: "Unknown encryption error")
95+
throw PasswordTransformerException.EncryptionFailed(
96+
"${e::class.simpleName}: ${e.message ?: "Unknown encryption error"}"
97+
)
9598
}
9699
}
97100

101+
@Suppress("TooGenericExceptionCaught")
98102
override fun decrypt(password: String): String {
99103
try {
100104
val combined = Base64.decode(password, Base64.NO_WRAP)
101105

102-
if (combined.size < GCM_IV_SIZE + GCM_TAG_SIZE) {
103-
throw IllegalArgumentException("Ciphertext too short")
104-
}
106+
require(combined.size >= GCM_IV_SIZE + GCM_TAG_SIZE) { "Ciphertext too short" }
105107

106108
val iv = combined.copyOfRange(0, GCM_IV_SIZE)
107109
val ciphertext = combined.copyOfRange(GCM_IV_SIZE, combined.size)
@@ -114,14 +116,17 @@ class KeystorePasswordTransformer(alias: String = DEFAULT_ALIAS) : PasswordTrans
114116
} catch (e: PasswordTransformerException) {
115117
throw e
116118
} catch (e: Exception) {
117-
throw PasswordTransformerException.DecryptionFailed(e.message ?: "Unknown decryption error")
119+
throw PasswordTransformerException.DecryptionFailed(
120+
"${e::class.simpleName}: ${e.message ?: "Unknown decryption error"}"
121+
)
118122
}
119123
}
120124

121125
companion object {
122126
private const val DEFAULT_ALIAS = "wordpress-rs-password-transformer"
123127
private const val KEYSTORE_PROVIDER = "AndroidKeyStore"
124128
private const val TRANSFORMATION = "AES/GCM/NoPadding"
129+
private const val AES_KEY_SIZE = 256
125130
private const val GCM_IV_SIZE = 12
126131
private const val GCM_TAG_SIZE_BITS = 128
127132
private const val GCM_TAG_SIZE = GCM_TAG_SIZE_BITS / 8
@@ -144,7 +149,7 @@ class KeystorePasswordTransformer(alias: String = DEFAULT_ALIAS) : PasswordTrans
144149
)
145150
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
146151
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
147-
.setKeySize(256)
152+
.setKeySize(AES_KEY_SIZE)
148153

149154
if (strongBox && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
150155
builder.setIsStrongBoxBacked(true)

wp_mobile/src/persistence/aes_gcm_transformer.rs

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
use aes_gcm::aead::rand_core::RngCore;
12
use aes_gcm::aead::{Aead, KeyInit, OsRng};
23
use aes_gcm::{AeadCore, Aes256Gcm, Key, Nonce};
3-
use base64::engine::general_purpose::STANDARD as BASE64;
44
use base64::Engine;
5+
use base64::engine::general_purpose::STANDARD as BASE64;
56
use hkdf::Hkdf;
6-
use aes_gcm::aead::rand_core::RngCore;
77
use sha2::Sha256;
88
use zeroize::Zeroize;
99

10-
use super::account_repository::{DecryptedPassword, EncryptedPassword, PasswordTransformer, PasswordTransformerError};
10+
use super::account_repository::{
11+
DecryptedPassword, EncryptedPassword, PasswordTransformer, PasswordTransformerError,
12+
};
1113

1214
const SALT_SIZE: usize = 32;
1315

@@ -85,19 +87,22 @@ impl AesGcmPasswordTransformer {
8587

8688
#[uniffi::export]
8789
impl PasswordTransformer for AesGcmPasswordTransformer {
88-
fn encrypt(&self, password: DecryptedPassword) -> Result<EncryptedPassword, PasswordTransformerError> {
90+
fn encrypt(
91+
&self,
92+
password: DecryptedPassword,
93+
) -> Result<EncryptedPassword, PasswordTransformerError> {
8994
let mut salt = [0u8; SALT_SIZE];
9095
OsRng.fill_bytes(&mut salt);
9196

9297
let mut key = self.derive_key(&salt);
9398
let cipher = Aes256Gcm::new(&key);
9499
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
95100

96-
let result = cipher
97-
.encrypt(&nonce, password.0.as_bytes())
98-
.map_err(|e| PasswordTransformerError::EncryptionFailed {
101+
let result = cipher.encrypt(&nonce, password.0.as_bytes()).map_err(|e| {
102+
PasswordTransformerError::EncryptionFailed {
99103
reason: e.to_string(),
100-
});
104+
}
105+
});
101106
key.zeroize();
102107
let ciphertext = result?;
103108

@@ -110,40 +115,60 @@ impl PasswordTransformer for AesGcmPasswordTransformer {
110115
Ok(EncryptedPassword(encoded))
111116
}
112117

113-
fn decrypt(&self, password: EncryptedPassword) -> Result<DecryptedPassword, PasswordTransformerError> {
118+
fn decrypt(
119+
&self,
120+
password: EncryptedPassword,
121+
) -> Result<DecryptedPassword, PasswordTransformerError> {
114122
let parse_err = |msg: &str| PasswordTransformerError::DecryptionFailed {
115123
reason: msg.to_string(),
116124
};
117125

118126
let mut parts = password.0.splitn(3, ':');
119-
let salt_b64 = parts.next().ok_or_else(|| parse_err("invalid encrypted password format"))?;
120-
let nonce_b64 = parts.next().ok_or_else(|| parse_err("invalid encrypted password format"))?;
121-
let ciphertext_b64 = parts.next().ok_or_else(|| parse_err("invalid encrypted password format"))?;
122-
123-
let salt = BASE64.decode(salt_b64).map_err(|e| PasswordTransformerError::DecryptionFailed {
124-
reason: e.to_string(),
125-
})?;
126-
let nonce_bytes = BASE64.decode(nonce_b64).map_err(|e| PasswordTransformerError::DecryptionFailed {
127-
reason: e.to_string(),
128-
})?;
127+
let salt_b64 = parts
128+
.next()
129+
.ok_or_else(|| parse_err("invalid encrypted password format"))?;
130+
let nonce_b64 = parts
131+
.next()
132+
.ok_or_else(|| parse_err("invalid encrypted password format"))?;
133+
let ciphertext_b64 = parts
134+
.next()
135+
.ok_or_else(|| parse_err("invalid encrypted password format"))?;
136+
137+
let salt =
138+
BASE64
139+
.decode(salt_b64)
140+
.map_err(|e| PasswordTransformerError::DecryptionFailed {
141+
reason: e.to_string(),
142+
})?;
143+
let nonce_bytes =
144+
BASE64
145+
.decode(nonce_b64)
146+
.map_err(|e| PasswordTransformerError::DecryptionFailed {
147+
reason: e.to_string(),
148+
})?;
129149
if nonce_bytes.len() != 12 {
130150
return Err(PasswordTransformerError::DecryptionFailed {
131-
reason: format!("invalid nonce length: expected 12, got {}", nonce_bytes.len()),
151+
reason: format!(
152+
"invalid nonce length: expected 12, got {}",
153+
nonce_bytes.len()
154+
),
132155
});
133156
}
134157
let nonce = Nonce::from_slice(&nonce_bytes);
135-
let ciphertext = BASE64.decode(ciphertext_b64).map_err(|e| PasswordTransformerError::DecryptionFailed {
136-
reason: e.to_string(),
158+
let ciphertext = BASE64.decode(ciphertext_b64).map_err(|e| {
159+
PasswordTransformerError::DecryptionFailed {
160+
reason: e.to_string(),
161+
}
137162
})?;
138163

139164
let mut key = self.derive_key(&salt);
140165
let cipher = Aes256Gcm::new(&key);
141166

142-
let result = cipher
143-
.decrypt(&nonce, ciphertext.as_ref())
144-
.map_err(|e| PasswordTransformerError::DecryptionFailed {
167+
let result = cipher.decrypt(nonce, ciphertext.as_ref()).map_err(|e| {
168+
PasswordTransformerError::DecryptionFailed {
145169
reason: e.to_string(),
146-
});
170+
}
171+
});
147172
key.zeroize();
148173
let plaintext = result?;
149174

0 commit comments

Comments
 (0)