Skip to content

Replace AbstractSecretKeyLoader with ISecretKeyLoader, Fixes AB#3297746 #2666

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: dev
Choose a base branch
from

Conversation

p3dr0rv
Copy link
Contributor

@p3dr0rv p3dr0rv commented Jun 12, 2025

In the next PR:

  • We are replacing AbstractSecretKeyLoader with ISecretKeyLoader.
  • We are introducing AndroidWrappedKeyLoaderFactory, which will return either the current implementation or the new one. For now, regardless of whether the feature flag is enabled or disabled, it will return the same object. In the following PR, this will be updated to return the new implementation based on the flag.
  • We are also delegating the secret key generation to a new class to separate concerns and improve code readability.

All these changes lay the groundwork for the next PR, where the new implementation will be introduced and the feature flag will be used to switch between the two implementations.

AB#3297746

Copy link

❌ Work item link check failed. Description does not contain AB#{ID}.

Click here to Learn more.

@p3dr0rv p3dr0rv marked this pull request as ready for review June 12, 2025 00:24
@Copilot Copilot AI review requested due to automatic review settings June 12, 2025 00:24
@p3dr0rv p3dr0rv requested a review from a team as a code owner June 12, 2025 00:24
Copilot

This comment was marked as outdated.

Copy link

✅ Work item link check complete. Description contains link AB#3297746 to an Azure Boards work item.

@github-actions github-actions bot changed the title Replace AbstractSecretKeyLoader with ISecretKeyLoader Replace AbstractSecretKeyLoader with ISecretKeyLoader, Fixes AB#3297746 Jun 12, 2025
@p3dr0rv p3dr0rv requested a review from Copilot June 12, 2025 03:48
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR replaces the deprecated AbstractSecretKeyLoader with the new ISecretKeyLoader interface, introduces the AndroidWrappedKeyLoaderFactory for future runtime switching of loader implementations, and delegates secret key generation to a dedicated generator class. Key changes include:

  • Refactoring all key loader references from AbstractSecretKeyLoader to ISecretKeyLoader.
  • Adding the getCipherTransformation method and updating encryption/decryption flows.
  • Introducing a feature flag (ENABLE_NEW_ANDROID_WRAPPED_KEY_LOADER) and a new factory to support future loader changes.

Reviewed Changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
common4j/src/test/com/microsoft/identity/common/java/crypto/key/AES256SecretKeyGeneratorTest.kt Added tests for AES256SecretKeyGenerator functionality.
common4j/src/test/com/microsoft/identity/common/java/crypto/StorageEncryptionManagerTest.java Updated tests to reference ISecretKeyLoader instead of AbstractSecretKeyLoader.
common4j/src/test/com/microsoft/identity/common/java/crypto/MockStorageEncryptionManager.java Refactored key loader types to use ISecretKeyLoader.
common4j/src/test/com/microsoft/identity/common/java/crypto/MockAES256KeyLoaderWithGetKeyError.java Added getCipherTransformation implementation.
common4j/src/test/com/microsoft/identity/common/java/crypto/MockAES256KeyLoader.java Updated secret key generation calls to use the new method.
common4j/src/main/com/microsoft/identity/common/java/flighting/CommonFlight.java Added the new feature flag for the Android wrapped key loader.
common4j/src/main/com/microsoft/identity/common/java/crypto/key/PredefinedKeyLoader.java Updated key loading and method signatures to work with ISecretKeyLoader.
common4j/src/main/com/microsoft/identity/common/java/crypto/key/AES256KeyLoader.java Modified to implement ISecretKeyLoader and updated key generator retrieval.
common/src/main/java/com/microsoft/identity/common/crypto/AndroidWrappedKeyLoaderFactory.kt Introduced a new factory to choose between loader implementations based on feature flags.
common/src/main/java/com/microsoft/identity/common/crypto/AndroidWrappedKeyLoader.java Refactored to use getCipherTransformation and updated key unwrapping logic.
common/src/main/java/com/microsoft/identity/common/crypto/AndroidAuthSdkStorageEncryptionManager.java Updated to integrate ISecretKeyLoader and the new wrapped key loader factory.
common/src/androidTest/java/com/microsoft/identity/common/crypto/AndroidWrappedKeyLoaderTest.java Updated tests to reflect changes in key algorithm referencing.
Comments suppressed due to low confidence (1)

common4j/src/main/com/microsoft/identity/common/java/crypto/key/PredefinedKeyLoader.java:53

  • [nitpick] If rawBytes is expected to be non-null, consider adding a @nonnull annotation for clarity and to prevent potential null-related issues.
public PredefinedKeyLoader(@NonNull final String alias, final byte[] rawBytes) {

* specific loader implementation should be used, allowing for runtime switching between
* different implementations without affecting client code.
*/
object AndroidWrappedKeyLoaderFactory {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than a keyloader factory, it looks like you need a factory for storage layer instead?

two ways to tackle this

  1. the new storage layer can decrypt (read) with both old and new keyloader. it would only write with the new keyloader

  2. the storage re-encrypts its data with the new keyloader, and use the new keyloader to read/write.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we simply use the flight to switch here - it would lead to user's data loss (since they can't decrypt existing data)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I’m planning to address this in the next PR, where I’ll be using strategy 1, see ->

override fun unwrapKey(wrappedSecretKey: ByteArray, secretKeyAlgorithm: String): SecretKey {

Instead of handling it at the storage layer as you mentioned, I’m just plugging in a new keyloader. This new keyloader will be easier to update if we need to introduce a new algorithm, whether for the key itself or the key-encryption-key.

@p3dr0rv p3dr0rv added the Skip-Consumers-Check Only include this if making a breaking change purposefully, and there is an MSAL/ADAL/Broker PR label Jun 20, 2025
fun createWrappedKeyLoader(
keyIdentifier: String,
fileName: String,
context: android.content.Context
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

android.content.Context

nit: Context

* This should be compatible with cryptographic providers, such as
* those used with KeyGenerator.getInstance(algorithm).
*/
val keyAlgorithm: String
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need these?

@@ -177,12 +185,11 @@ public synchronized SecretKey getKey() throws ClientException {
return key;
}

@Override
@NonNull
protected SecretKey generateRandomKey() throws ClientException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protected

private?

* different implementations without affecting client code.
*/
object AndroidWrappedKeyLoaderFactory {
const val WRAPPED_KEY_KEY_IDENTIFIER: String = "A001"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WRAPPED_KEY_KEY_IDENTIFIER

do you need this here? (maybe for next pr)

/**
* Flight to enable the new Android wrapped key loader.
*/
ENABLE_NEW_ANDROID_WRAPPED_KEY_LOADER("EnableNewAndroidWrappedKeyLoader", true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need this in this PR?

You could add this in next PR and factory class

*
* [ISecretKeyLoader] provides a consistent abstraction layer for cryptographic key operations
*/
interface ISecretKeyLoader {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISecretKeyLoader

Given it's functionality, I think, a better name would be ISecretKeyProvider.

your call.

Copy link
Contributor

@mohitc1 mohitc1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some suggestions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Skip-Consumers-Check Only include this if making a breaking change purposefully, and there is an MSAL/ADAL/Broker PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants