Skip to content
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

implement EKM integration to load private keys during setup #279

Closed
6 tasks done
tomholub opened this issue Mar 20, 2021 · 15 comments · Fixed by #434
Closed
6 tasks done

implement EKM integration to load private keys during setup #279

tomholub opened this issue Mar 20, 2021 · 15 comments · Fixed by #434
Assignees

Comments

@tomholub
Copy link
Collaborator

tomholub commented Mar 20, 2021

EKM = Email Key Manager https://flowcrypt.com/docs/technical/enterprise/email-deployment-overview.html

OrgRule definitions https://flowcrypt.com/docs/business/org-rules.html

As a part of #275 and after #276 and #277 , immediately after authentication when we receive the OIDC and OrgRules, we should check if orgRules.usesKeyManager() == true. If yes, we should:

  • 7) call GET <ekm>/v1/keys/private. Into authorization header please put Bearer <ID_TOKEN>. On error, offer retry
  • 8) if there are no private keys there (empty array), show an error to the user that there are no private keys configured for them and that they should ask their systems administrator or help desk. Offer retry
  • 9) check that all of the received private keys are fully decrypted
  • 10) if there is at least one private key, ask user to provide a passphrase (similar UI to creating a new key), then ask to confirm the pass phrase
  • 11) encrypt the received keys with the pass phrase. Keep pass phrase in memory option to keep pass phrase only in memory #197 , store encrypted key in storage
  • 12) finish setup without any further user interaction

The goal is that if user has keys already configured on EKM and appropriate OrgRules are in place, they only need to authenticate and choose a pass phrase, and everything will be done automatically. After authentication and successful automatic setup, they will be sent to their inbox.

In this flow, do not submit any public key to attester.

@tomholub tomholub added this to the Second priority milestone Mar 20, 2021
@tomholub tomholub mentioned this issue Mar 20, 2021
13 tasks
@tomholub tomholub changed the title implement EKM integration to load private keys during startup implement EKM integration to load private keys during setup Apr 28, 2021
@tomholub
Copy link
Collaborator Author

tomholub commented May 11, 2021

Here a flow chart

image

@ekievsky
Copy link
Contributor

ekievsky commented Jul 29, 2021

I will split it to 2 PRs:
FIrst:

  • if there are no private keys there (empty array), show an error to the user that there are no private keys configured for them and that they should ask their systems administrator or help desk. Offer retry
  • check that all of the received private keys are fully decrypted

Second:

  • if there is at least one private key, ask user to provide a passphrase (similar UI to creating a new key), then ask to confirm the pass phrase
  • encrypt the received keys with the pass phrase. Keep pass phrase in memory option to keep pass phrase only in memory
  • finish setup without any further user interaction

@tomholub
Copy link
Collaborator Author

sounds good

@ekievsky
Copy link
Contributor

ekievsky commented Aug 1, 2021

Here is the 2 questions popped up:

  • how do we make sure that private keys are decrypted?
  • What is the flow for encrypting the received keys with the pass phrase?

@tomholub
Copy link
Collaborator Author

tomholub commented Aug 1, 2021

how do we make sure that private keys are decrypted?

Parse each key armored string with Core.parseKeys. The result should always be exactly one OpenPGP key per armored string. It must be a private key and it must have isFullyDecrypted == true.

What is the flow for encrypting the received keys with the pass phrase?

Please add a method to Core that looks like this:

    func encryptKey(armoredPrv: String, passphrase: String) throws -> CoreRes.DecryptKey {
        let r = try call("encryptKey", jsonDict: ["armored": armoredPrv, "passphrase": passphrase], data: nil)
        return try r.json.decodeJson(as: CoreRes.EncryptKey.self)
    }

Core types:

    struct EncryptKey: Decodable {
        let encryptedKey: String
    }

Then use Core.encryptKey to encrypt the received keys.

@ekievsky
Copy link
Contributor

ekievsky commented Aug 2, 2021

Parse each key armored string with Core.parseKeys. The result should always be exactly one OpenPGP key per armored string. It must be a private key and it must have isFullyDecrypted == true.

These keys are received in following JSON:
"{\"privateKeys\":[{\"decryptedPrivateKey\":\"-----BEGIN PGP PRIVATE KEY BLOCK-----\\nVersion: BCPG v1.69\\n\\nlFgEYL/CoBYJKwYBBAHaRw8BAQdAY0jxarPi12nHs9wMHw1D4R......"}]}", so they are decrypted. Is there a case when keys are encrypted?

@tomholub
Copy link
Collaborator Author

tomholub commented Aug 2, 2021 via email

@ekievsky
Copy link
Contributor

ekievsky commented Aug 2, 2021

Should we show an alert warning that keys are not fully decrypted or what's the flow in that case?

@tomholub
Copy link
Collaborator Author

tomholub commented Aug 2, 2021

Show an alert and send user back to login screen. They can click Continue with Gmail again to retry.

tomholub added a commit that referenced this issue Aug 3, 2021
…ys; (#430)

Co-authored-by: ykyivskyi-gd <yevhen.kyivskyi@glassdoor.com>
Co-authored-by: Tom J <6306961+tomholub@users.noreply.github.com>
@ekievsky
Copy link
Contributor

ekievsky commented Aug 4, 2021

When user creates a new key we call a method from Core generateKey(....) which returns CoreRes.GenerateKey and it contains a KeyDetails, but new method encryptKey(....) returns CoreRes.EncryptKey which has String is that a typo? Because to save a key in storage and update it we need KeyDetails.

@ekievsky
Copy link
Contributor

ekievsky commented Aug 4, 2021

also, while making a request to get private keys from EKM, we receive array of keys, should we use the first key from array?

@tomholub
Copy link
Collaborator Author

tomholub commented Aug 4, 2021 via email

@tomholub
Copy link
Collaborator Author

tomholub commented Aug 4, 2021 via email

@ekievsky
Copy link
Contributor

ekievsky commented Aug 4, 2021

array of keys, should we use the first key from array? no - we have to save all of the keys. an account can have more than one private key saved. thats why when you go to settings -> keys, it will render a list.

our Passphrase entity creates with fingeprints for one key and there is updateKey and testWelcome requests on AttesterApi which takes 1 keys, how should I deal with it?
and which key should be encrypted/parsed?

@tomholub
Copy link
Collaborator Author

tomholub commented Aug 4, 2021 via email

tomholub added a commit that referenced this issue Aug 15, 2021
* Handled empty or not decrypted keys while searching EKM keys;

* Added passphrase setup if any key present in EKM;

* Created abstract view controller for passphrase creation;
Fixed PR comments;

* fix bug when more than one key is used

* Saving passphrase in memory for EKM flow;

Co-authored-by: ykyivskyi-gd <yevhen.kyivskyi@glassdoor.com>
Co-authored-by: Tom J <6306961+tomholub@users.noreply.github.com>
Co-authored-by: Tom <tom@flowcrypt.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants