Example #1
0
func (o *EncryptOptions) Encrypt() error {
	// Get data
	var data []byte
	var warnWhitespace = true
	switch {
	case len(o.CleartextFile) > 0:
		if d, err := ioutil.ReadFile(o.CleartextFile); err != nil {
			return err
		} else {
			data = d
		}
	case len(o.CleartextData) > 0:
		// Don't warn in cases where we're explicitly being given the data to use
		warnWhitespace = false
		data = o.CleartextData
	case o.CleartextReader != nil && util.IsTerminalReader(o.CleartextReader) && o.PromptWriter != nil:
		// Read a single line from stdin with prompting
		data = []byte(util.PromptForString(o.CleartextReader, o.PromptWriter, "Data to encrypt: "))
	case o.CleartextReader != nil:
		// Read data from stdin without prompting (allows binary data and piping)
		if d, err := ioutil.ReadAll(o.CleartextReader); err != nil {
			return err
		} else {
			data = d
		}
	}
	if warnWhitespace && (o.PromptWriter != nil) && (len(data) > 0) {
		r1, _ := utf8.DecodeRune(data)
		r2, _ := utf8.DecodeLastRune(data)
		if unicode.IsSpace(r1) || unicode.IsSpace(r2) {
			fmt.Fprintln(o.PromptWriter, "Warning: Data includes leading or trailing whitespace, which will be included in the encrypted value")
		}
	}

	// Get key
	var key []byte
	switch {
	case len(o.KeyFile) > 0:
		if block, ok, err := pemutil.BlockFromFile(o.KeyFile, configapi.StringSourceKeyBlockType); err != nil {
			return err
		} else if !ok {
			return fmt.Errorf("%s does not contain a valid PEM block of type %q", o.KeyFile, configapi.StringSourceKeyBlockType)
		} else if len(block.Bytes) == 0 {
			return fmt.Errorf("%s does not contain a key", o.KeyFile)
		} else {
			key = block.Bytes
		}
	case len(o.GenKeyFile) > 0:
		key = make([]byte, 32)
		if _, err := rand.Read(key); err != nil {
			return err
		}
	}
	if len(key) == 0 {
		return errors.New("--genkey or --key is required")
	}

	// Encrypt
	dataBlock, err := x509.EncryptPEMBlock(rand.Reader, configapi.StringSourceEncryptedBlockType, data, key, x509.PEMCipherAES256)
	if err != nil {
		return err
	}

	// Write data
	if len(o.EncryptedFile) > 0 {
		if err := pemutil.BlockToFile(o.EncryptedFile, dataBlock, os.FileMode(0644)); err != nil {
			return err
		}
	} else if o.EncryptedWriter != nil {
		encryptedBytes, err := pemutil.BlockToBytes(dataBlock)
		if err != nil {
			return err
		}
		n, err := o.EncryptedWriter.Write(encryptedBytes)
		if err != nil {
			return err
		}
		if n != len(encryptedBytes) {
			return fmt.Errorf("could not completely write encrypted data")
		}
	}

	// Write key
	if len(o.GenKeyFile) > 0 {
		keyBlock := &pem.Block{Bytes: key, Type: configapi.StringSourceKeyBlockType}
		if err := pemutil.BlockToFile(o.GenKeyFile, keyBlock, os.FileMode(0600)); err != nil {
			return err
		}
	}

	return nil
}
Example #2
0
func (o *DecryptOptions) Decrypt() error {
	// Get PEM data block
	var data []byte
	switch {
	case len(o.EncryptedFile) > 0:
		if d, err := ioutil.ReadFile(o.EncryptedFile); err != nil {
			return err
		} else {
			data = d
		}
	case len(o.EncryptedData) > 0:
		data = o.EncryptedData
	case o.EncryptedReader != nil && !util.IsTerminalReader(o.EncryptedReader):
		if d, err := ioutil.ReadAll(o.EncryptedReader); err != nil {
			return err
		} else {
			data = d
		}
	}
	if len(data) == 0 {
		return fmt.Errorf("no input data specified")
	}
	dataBlock, ok := pemutil.BlockFromBytes(data, configapi.StringSourceEncryptedBlockType)
	if !ok {
		return fmt.Errorf("input does not contain a valid PEM block of type %q", configapi.StringSourceEncryptedBlockType)
	}

	// Get password
	keyBlock, ok, err := pemutil.BlockFromFile(o.KeyFile, configapi.StringSourceKeyBlockType)
	if err != nil {
		return err
	}
	if !ok {
		return fmt.Errorf("%s does not contain a valid PEM block of type %q", o.KeyFile, configapi.StringSourceKeyBlockType)
	}
	if len(keyBlock.Bytes) == 0 {
		return fmt.Errorf("%s does not contain a key", o.KeyFile)
	}
	password := keyBlock.Bytes

	// Decrypt
	plaintext, err := x509.DecryptPEMBlock(dataBlock, password)
	if err != nil {
		return err
	}

	// Write decrypted data
	switch {
	case len(o.DecryptedFile) > 0:
		if err := ioutil.WriteFile(o.DecryptedFile, plaintext, os.FileMode(0600)); err != nil {
			return err
		}
	case o.DecryptedWriter != nil:
		fmt.Fprint(o.DecryptedWriter, string(plaintext))
		if util.IsTerminalWriter(o.DecryptedWriter) {
			fmt.Fprintln(o.DecryptedWriter)
		}
	}

	return nil
}