Compare commits

...

2 commits

4 changed files with 33 additions and 63 deletions

View file

@ -30,14 +30,7 @@ func (c *Client) CheckSession(ctx context.Context) bool {
func (c *Client) Login(ctx context.Context) error {
c.csrfToken = http.Cookie{}
privateKey, err := c.getPrivateKey(c.userPrivateKey, c.userPassword)
if err != nil {
return fmt.Errorf("Parsing User Private Key: %w", err)
}
defer privateKey.ClearPrivateParams()
data := Login{&GPGAuth{KeyID: privateKey.GetFingerprint()}}
data := Login{&GPGAuth{KeyID: c.userPrivateKey.GetFingerprint()}}
res, _, err := c.DoCustomRequestAndReturnRawResponse(ctx, "POST", "/auth/login.json", "v2", data, nil)
if err != nil && !strings.Contains(err.Error(), "Error API JSON Response Status: Message: The authentication failed.") {

View file

@ -26,8 +26,8 @@ type Client struct {
// userPublicKey has been removed since it can be gotten from the private userPrivateKey
userPassword []byte
userPrivateKey string
// be sure to make a copy since using ClearPrivateParams on a handler also wipes the key...
userPrivateKey *crypto.Key
userID string
// Server Settings Determining which Resource Types we can use
@ -71,23 +71,13 @@ func NewClient(httpClient *http.Client, UserAgent, BaseURL, UserPrivateKey, User
pgp := crypto.PGP()
// Verify that the Given Privatekey and Password are valid and work Together if we were provieded one
var unlockedKey *crypto.Key = nil
if UserPrivateKey != "" {
privateKeyObj, err := crypto.NewKeyFromArmored(UserPrivateKey)
key, err := GetPrivateKeyFromArmor(UserPrivateKey, []byte(UserPassword))
if err != nil {
return nil, fmt.Errorf("Unable to Create Key From UserPrivateKey string: %w", err)
return nil, fmt.Errorf("Get Private Key: %w", err)
}
unlockedKeyObj, err := privateKeyObj.Unlock([]byte(UserPassword))
if err != nil {
return nil, fmt.Errorf("Unable to Unlock UserPrivateKey using UserPassword: %w", err)
}
privateKeyRing, err := crypto.NewKeyRing(unlockedKeyObj)
if err != nil {
return nil, fmt.Errorf("Unable to Create a new Key Ring using the unlocked UserPrivateKey: %w", err)
}
// Cleanup Secrets
privateKeyRing.ClearPrivateParams()
unlockedKey = key
}
// Create Client Object
@ -95,8 +85,7 @@ func NewClient(httpClient *http.Client, UserAgent, BaseURL, UserPrivateKey, User
httpClient: httpClient,
baseURL: u,
userAgent: UserAgent,
userPassword: []byte(UserPassword),
userPrivateKey: UserPrivateKey,
userPrivateKey: unlockedKey,
pgp: pgp,
}
return c, err
@ -207,11 +196,11 @@ func (c *Client) GetPublicKey(ctx context.Context) (string, string, error) {
}
// Lets get the actual Fingerprint instead of trusting the Server
privateKeyObj, err := crypto.NewKeyFromArmored(c.userPrivateKey)
serverKey, err := crypto.NewKeyFromArmored(body.Keydata)
if err != nil {
return "", "", fmt.Errorf("Parsing Server Key: %w", err)
}
return body.Keydata, privateKeyObj.GetFingerprint(), nil
return body.Keydata, serverKey.GetFingerprint(), nil
}
// setMetadataTypeSettings Gets and configures the Client to use the Types the Server wants us to use

View file

@ -8,14 +8,12 @@ import (
// EncryptMessage encrypts a message using the users public key and then signes the message using the users private key
func (c *Client) EncryptMessage(message string) (string, error) {
key, err := c.getPrivateKey(c.userPrivateKey, c.userPassword)
key, err := c.userPrivateKey.Copy()
if err != nil {
return "", fmt.Errorf("Get Private Key: %w", err)
return "", fmt.Errorf("Get Private Key Copy: %w", err)
}
defer key.ClearPrivateParams()
encHandle, err := c.pgp.Encryption().SigningKey(key).Recipient(key).New()
encHandle, err := c.pgp.Encryption().SigningKey(key).Recipient(c.userPrivateKey).New()
if err != nil {
return "", fmt.Errorf("New Encryptor: %w", err)
}
@ -36,18 +34,16 @@ func (c *Client) EncryptMessage(message string) (string, error) {
// EncryptMessageWithPublicKey encrypts a message using the provided public key and then signes the message using the users private key
func (c *Client) EncryptMessageWithPublicKey(publickey, message string) (string, error) {
key, err := c.getPrivateKey(c.userPrivateKey, c.userPassword)
if err != nil {
return "", fmt.Errorf("Get Private Key: %w", err)
}
defer key.ClearPrivateParams()
publicKey, err := crypto.NewKeyFromArmored(publickey)
if err != nil {
return "", fmt.Errorf("Get Public Key: %w", err)
}
key, err := c.userPrivateKey.Copy()
if err != nil {
return "", fmt.Errorf("Get Private Key Copy: %w", err)
}
encHandle, err := c.pgp.Encryption().SigningKey(key).Recipient(publicKey).New()
if err != nil {
return "", fmt.Errorf("New Encryptor: %w", err)
@ -68,29 +64,31 @@ func (c *Client) EncryptMessageWithPublicKey(publickey, message string) (string,
}
// DecryptMessage decrypts a message using the users Private Key
func (c *Client) DecryptMessage(message string) (string, error) {
message, _, err := c.DecryptMessageWithPrivateKeyAndReturnSessionKey(c.userPrivateKey, c.userPassword, message)
func (c *Client) DecryptMessage(armoredCiphertext string) (string, error) {
key, err := c.userPrivateKey.Copy()
if err != nil {
return "", fmt.Errorf("Get Private Key Copy: %w", err)
}
message, _, err := c.DecryptMessageWithPrivateKeyAndReturnSessionKey(key, armoredCiphertext)
return message, err
}
// DecryptMessageWithPrivateKey Decrypts a Message using the Provided Private Key
// Returns the Session key so that it can be saved in a cache
func (c *Client) DecryptMessageWithPrivateKeyAndReturnSessionKey(privateKey string, passphrase []byte, ciphertextArmored string) (string, *crypto.SessionKey, error) {
key, err := c.getPrivateKey(privateKey, passphrase)
if err != nil {
return "", nil, fmt.Errorf("Get Private Key: %w", err)
}
func (c *Client) DecryptMessageWithPrivateKeyAndReturnSessionKey(privateKey *crypto.Key, armoredCiphertext string) (string, *crypto.SessionKey, error) {
defer key.ClearPrivateParams()
decHandle, err := c.pgp.Decryption().DecryptionKey(key).RetrieveSessionKey().New()
decHandle, err := c.pgp.Decryption().
DecryptionKey(privateKey).
RetrieveSessionKey().
New()
if err != nil {
return "", nil, fmt.Errorf("New Decryptor: %w", err)
}
defer decHandle.ClearPrivateParams()
res, err := decHandle.Decrypt([]byte(ciphertextArmored), crypto.Armor)
res, err := decHandle.Decrypt([]byte(armoredCiphertext), crypto.Armor)
if err != nil {
return "", nil, fmt.Errorf("Decrypt: %w", err)
}
@ -98,11 +96,7 @@ func (c *Client) DecryptMessageWithPrivateKeyAndReturnSessionKey(privateKey stri
return res.String(), res.SessionKey(), nil
}
func (c *Client) getPrivateKey(privateKey string, passphrase []byte) (*crypto.Key, error) {
if c.userPrivateKey == "" {
return nil, fmt.Errorf("Client has no Private Key")
}
func GetPrivateKeyFromArmor(privateKey string, passphrase []byte) (*crypto.Key, error) {
key, err := crypto.NewKeyFromArmored(privateKey)
if err != nil {
return nil, fmt.Errorf("Key From Armored: %w", err)

View file

@ -5,7 +5,6 @@ import (
"fmt"
"strings"
"github.com/ProtonMail/gopenpgp/v3/crypto"
"github.com/google/uuid"
)
@ -44,15 +43,10 @@ func (c *Client) SetupServerVerification(ctx context.Context) (string, string, e
// VerifyServer verifys that the Server is still the same one as during the Setup, Only works before login
func (c *Client) VerifyServer(ctx context.Context, token, encToken string) error {
privateKeyObj, err := crypto.NewKeyFromArmored(c.userPrivateKey)
if err != nil {
return fmt.Errorf("Parsing User Private Key: %w", err)
}
data := GPGVerifyContainer{
Req: GPGVerify{
Token: encToken,
KeyID: privateKeyObj.GetFingerprint(),
KeyID: c.userPrivateKey.GetFingerprint(),
},
}
raw, _, err := c.DoCustomRequestAndReturnRawResponse(ctx, "POST", "/auth/verify.json", "v2", data, nil)