예제 #1
0
파일: load.go 프로젝트: bndw/pick
func Load(password []byte, backend backends.Client, encryptionClient crypto.Client, config *config.Config) (*Safe, error) {
	s := Safe{
		backend:  backend,
		crypto:   encryptionClient,
		password: password,
		Config:   config,
	}

	data, err := s.backend.Load()
	if err != nil {
		if _, ok := err.(*errors.SafeNotFound); ok {
			s.Accounts = make(map[string]Account)
			return &s, nil
		}
		return nil, err
	}

	safeDTO := safeDTO{}
	if err := json.Unmarshal(data, &safeDTO); err == nil {
		// Unmarshalling did succeed -> Safe uses new format
		// Do nothing
	} else {
		safeDTO.Ciphertext = data
		// If we don't have a config, use OpenPGP for backwards-compatibility
		defaultOpenPGPConfig := crypto.NewDefaultConfigWithType(crypto.ConfigTypeOpenPGP)
		safeDTO.Config = &defaultOpenPGPConfig
	}

	upgradeNeeded := false
	plaintext, err := s.crypto.Decrypt(safeDTO.Ciphertext, password)
	if err != nil {
		// Wasn't able to decrypt the safe with the default / user-provided config.
		// Now use config from the safe. If this doesn't work, then the password
		// is _definitely_ incorrect. If however decryption works now, we need
		// to upgrade the safe to use the default / user-provided config.
		userCrypto := s.crypto
		s.crypto, err = crypto.New(safeDTO.Config)
		if err != nil {
			return nil, err
		}
		plaintext, err = s.crypto.Decrypt(safeDTO.Ciphertext, password)
		if err != nil {
			return nil, err
		}
		// Safe upgrade is needed, restore default / user-provided config
		upgradeNeeded = true
		s.crypto = userCrypto
	}

	var tmp Safe

	if err := json.Unmarshal(plaintext, &tmp); err != nil {
		return nil, &errors.SafeCorrupt{}
	}

	s.Accounts = tmp.Accounts

	// We still need to compare the default / user-provided config with the safe config.
	// If they differ -> Upgrade safe
	// This check is required for the OpenPGP mode, as it gets its config from the ciphertext.
	if upgradeNeeded || !reflect.DeepEqual(*safeDTO.Config, s.Config.Encryption) {
		fmt.Println("Upgrading safe")
		if err := s.save(); err != nil {
			fmt.Println("Error", err.Error())
		}
	}

	return &s, err
}
예제 #2
0
파일: load_test.go 프로젝트: bndw/pick
		}
		for j, data := range safeData {
			backendClient.Data = []byte(data)
			s, err := safe.Load([]byte(password), backendClient, cryptoClient, conf)
			if err != nil {
				t.Fatalf("#%d.#%d: failed to load safe: %s", i, j, err.Error())
			}
			if _, err := s.Get("foo"); err != nil {
				t.Fatalf("#%d.#%d: failed to get 'foo' safe account: %s", i, j, err.Error())
			}
		}
	}
}

var safeCryptoConfigs = []crypto.Config{
	crypto.NewDefaultConfigWithType(crypto.ConfigTypeOpenPGP),
	crypto.Config{
		Type: crypto.ConfigTypeOpenPGP,
		OpenPGPSettings: &crypto.OpenPGPSettings{
			Cipher:   "aes128",
			S2KCount: 1024,
		},
	},
	crypto.Config{
		Type: crypto.ConfigTypeOpenPGP,
		OpenPGPSettings: &crypto.OpenPGPSettings{
			Cipher:   "aes256",
			S2KCount: 1024,
		},
	},
	crypto.Config{