Пример #1
0
func TestProcessPrivateKeyFile_encrypted(t *testing.T) {
	// Encrypt the file
	b, err := x509.EncryptPEMBlock(rand.Reader,
		"RSA PRIVATE KEY",
		[]byte("what"),
		[]byte("password"),
		x509.PEMCipherAES128)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	tf, err := ioutil.TempFile("", "packer")
	if err != nil {
		t.Fatalf("bad: %s", err)
	}
	defer os.Remove(tf.Name())

	err = pem.Encode(tf, b)
	tf.Close()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	path := tf.Name()

	// Should have an error with a bad password
	if _, err := processPrivateKeyFile(path, "bad"); err == nil {
		t.Fatal("should error")
	}

	if _, err := processPrivateKeyFile(path, "password"); err != nil {
		t.Fatalf("bad: %s", err)
	}
}
Пример #2
0
func readKeyOrGenerate(path, pass string) (*rsa.PrivateKey, error) {
	file, err := ioutil.ReadFile(path)
	var key *rsa.PrivateKey
	if err != nil {
		log.Printf("Generating new key %s...", path)
		key, err = rsa.GenerateKey(rand.Reader, rsaBitLength)
		if err != nil {
			return nil, err
		}
		raw := x509.MarshalPKCS1PrivateKey(key)
		block, err := x509.EncryptPEMBlock(rand.Reader, blockType, raw, []byte(pass), cipherType)
		if err != nil {
			return nil, err
		}
		encoded := pem.EncodeToMemory(block)
		ioutil.WriteFile(path, encoded, 0400)
	} else {
		log.Printf("Loading key %s...", path)
		block, _ := pem.Decode(file)
		if block == nil {
			return nil, fmt.Errorf("%s doesn't contain a PEM key", path)
		}
		raw, err := x509.DecryptPEMBlock(block, []byte(pass))
		if err != nil {
			return nil, err
		}
		key, err = x509.ParsePKCS1PrivateKey(raw)
		if err != nil {
			return nil, err
		}
	}
	return key, nil
}
Пример #3
0
// PrivateKeyToEncryptedPEM converts a private key to an encrypted PEM
func PrivateKeyToEncryptedPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
	switch k := privateKey.(type) {
	case *ecdsa.PrivateKey:
		if k == nil {
			return nil, errors.New("Invalid ecdsa private key. It must be different from nil.")
		}

		raw, err := x509.MarshalECPrivateKey(k)

		if err != nil {
			return nil, err
		}

		block, err := x509.EncryptPEMBlock(
			rand.Reader,
			"ECDSA PRIVATE KEY",
			raw,
			pwd,
			x509.PEMCipherAES256)

		if err != nil {
			return nil, err
		}

		return pem.EncodeToMemory(block), nil

	default:
		return nil, errors.New("Invalid key type. It must be *ecdsa.PrivateKey")
	}
}
Пример #4
0
func FuzzPEM(data []byte) int {
	var b pem.Block
	err := gob.NewDecoder(bytes.NewReader(data)).Decode(&b)
	if err != nil {
		return 0
	}
	b1, err := x509.DecryptPEMBlock(&b, []byte("pass"))
	if err != nil {
		return 0
	}
	b2, err := x509.EncryptPEMBlock(zeroReader(0), "msg", b1, []byte("pass1"), x509.PEMCipherDES)
	if err != nil {
		panic(err)
	}
	_, err = x509.DecryptPEMBlock(b2, []byte("pass"))
	if err == nil {
		panic("decoded with a wrong pass")
	}
	b3, err := x509.DecryptPEMBlock(b2, []byte("pass1"))
	if err != nil {
		panic(err)
	}
	if !bytes.Equal(b1, b3) {
		panic("data changed")
	}
	return 1
}
Пример #5
0
// PrivateKeyToEncryptedPEM converts a private key to an encrypted PEM
func PrivateKeyToEncryptedPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
	switch x := privateKey.(type) {
	case *ecdsa.PrivateKey:
		raw, err := x509.MarshalECPrivateKey(x)

		if err != nil {
			return nil, err
		}

		block, err := x509.EncryptPEMBlock(
			rand.Reader,
			"ECDSA PRIVATE KEY",
			raw,
			pwd,
			x509.PEMCipherAES256)

		if err != nil {
			return nil, err
		}

		return pem.EncodeToMemory(block), nil

	default:
		return nil, ErrInvalidKey
	}
}
Пример #6
0
// writeKey takes an unencrypted keyblock and, if the kek is not nil, encrypts it before
// writing it to disk.  If the kek is nil, writes it to disk unencrypted.
func (k *KeyReadWriter) writeKey(keyBlock *pem.Block, kekData KEKData, pkh PEMKeyHeaders) error {
	if kekData.KEK != nil {
		encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
			keyBlock.Type,
			keyBlock.Bytes,
			kekData.KEK,
			x509.PEMCipherAES256)
		if err != nil {
			return err
		}
		if encryptedPEMBlock.Headers == nil {
			return errors.New("unable to encrypt key - invalid PEM file produced")
		}
		keyBlock = encryptedPEMBlock
	}

	if pkh != nil {
		headers, err := pkh.MarshalHeaders(kekData)
		if err != nil {
			return err
		}
		mergePEMHeaders(keyBlock.Headers, headers)
	}
	keyBlock.Headers[versionHeader] = strconv.FormatUint(kekData.Version, 10)

	if err := ioutils.AtomicWriteFile(k.paths.Key, pem.EncodeToMemory(keyBlock), keyPerms); err != nil {
		return err
	}
	k.kekData = kekData
	k.headersObj = pkh
	return nil
}
Пример #7
0
// EncryptPrivateKey returns an encrypted PEM key given a Privatekey
// and a passphrase
func EncryptPrivateKey(key data.PrivateKey, role, passphrase string) ([]byte, error) {
	bt, err := blockType(key)
	if err != nil {
		return nil, err
	}

	password := []byte(passphrase)
	cipherType := x509.PEMCipherAES256

	encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
		bt,
		key.Private(),
		password,
		cipherType)
	if err != nil {
		return nil, err
	}

	if encryptedPEMBlock.Headers == nil {
		return nil, fmt.Errorf("unable to encrypt key - invalid PEM file produced")
	}
	encryptedPEMBlock.Headers["role"] = role

	return pem.EncodeToMemory(encryptedPEMBlock), nil
}
Пример #8
0
func EncodePEM(binary []byte, blockType string, password string) (pemBlock string, err error) {

	var blk *pem.Block
	/* Awaiting Go 1.1 */
	if password != "" {
		passwordBytes := ([]byte)(password)
		blk, err = x509.EncryptPEMBlock(rand.Reader, blockType, binary, passwordBytes, x509.PEMCipherAES256)
		if err != nil {
			return
		}
	} else {
		/* */
		blk = new(pem.Block)
		blk.Type = blockType
		blk.Bytes = binary
		/* Awaiting Go 1.1 */
	}
	/* */

	buf := new(bytes.Buffer)

	err = pem.Encode(buf, blk)
	if err != nil {
		return
	}

	pemBlock = buf.String()
	return
}
Пример #9
0
// EncryptPrivateKey returns an encrypted PEM key given a Privatekey
// and a passphrase
func EncryptPrivateKey(key *data.PrivateKey, passphrase string) ([]byte, error) {
	var blockType string
	algorithm := key.Algorithm()

	switch algorithm {
	case data.RSAKey:
		blockType = "RSA PRIVATE KEY"
	case data.ECDSAKey:
		blockType = "EC PRIVATE KEY"
	default:
		return nil, fmt.Errorf("only RSA or ECDSA keys are currently supported. Found: %s", algorithm)
	}

	password := []byte(passphrase)
	cipherType := x509.PEMCipherAES256

	encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
		blockType,
		key.Private(),
		password,
		cipherType)
	if err != nil {
		return nil, err
	}

	return pem.EncodeToMemory(encryptedPEMBlock), nil
}
Пример #10
0
// EncryptECPrivateKey receives a PEM encoded private key and returns an encrypted
// AES256 version using a passphrase
// TODO: Make this method generic to handle RSA keys
func EncryptECPrivateKey(key []byte, passphraseStr string) ([]byte, error) {
	passphrase := []byte(passphraseStr)
	cipherType := x509.PEMCipherAES256

	keyBlock, _ := pem.Decode(key)
	if keyBlock == nil {
		// This RootCA does not have a valid signer.
		return nil, fmt.Errorf("error while decoding PEM key")
	}

	encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
		"EC PRIVATE KEY",
		keyBlock.Bytes,
		passphrase,
		cipherType)
	if err != nil {
		return nil, err
	}

	if encryptedPEMBlock.Headers == nil {
		return nil, fmt.Errorf("unable to encrypt key - invalid PEM file produced")
	}

	return pem.EncodeToMemory(encryptedPEMBlock), nil
}
Пример #11
0
// export private key to pem format
func exportPrivateKeytoEncryptedPEM(sec *rsa.PrivateKey, password []byte) []byte {
	l := x509.MarshalPKCS1PrivateKey(sec)
	m, _ := x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", l, password, x509.PEMCipherAES256)
	n := pem.EncodeToMemory(m)
	//log.Print(string(n))

	return n
}
Пример #12
0
func (ck *RSACertKey) EncPemKey(passwd []byte) ([]byte, error) {
	//kpem := ck.PemKey()
	kpem := x509.MarshalPKCS1PrivateKey(ck.key)
	encblock, err := x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", kpem, passwd, x509.PEMCipherAES128)
	if err != nil {
		return nil, err
	}
	return pem.EncodeToMemory(encblock), nil
}
Пример #13
0
func (ck *ECCertKey) EncPkg(passwd string) ([]byte, error) {
	var pkgpem []byte
	pkgpem = append(pkgpem, ck.PemKey()...)
	pkgpem = append(pkgpem, ck.PemCert()...)
	encblock, err := x509.EncryptPEMBlock(rand.Reader, pkgTypeStr, pkgpem, []byte(passwd), x509.PEMCipherAES128)
	if err != nil {
		return nil, err
	}
	return pem.EncodeToMemory(encblock), nil
}
Пример #14
0
// export private key to pem format
func exportPrivateKeytoEncryptedPEM(sec *ecdsa.PrivateKey, password []byte) []byte {
	l, _ := x509.MarshalECPrivateKey(sec)
	m, _ := x509.EncryptPEMBlock(rand.Reader, "EC PRIVATE KEY", l, password, x509.PEMCipherAES256)
	n := pem.EncodeToMemory(m)
	//log.Print(string(n))

	keypem, _ := os.OpenFile("sec.Encrypted.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	pem.Encode(keypem, &pem.Block{Type: "EC PRIVATE KEY", Bytes: l})

	return n
}
Пример #15
0
func _generateKey(passpharse []byte, config ConfigType) (pubBlock, priBlock *pem.Block, err error) {
	encodepasspharse := _passpharseHash(passpharse, config.Way)
	pri, err := rsa.GenerateKey(rand.Reader, config.KeyLength)
	if err != nil {
		return
	}
	//public key encoding
	pubbyte, err := x509.MarshalPKIXPublicKey(pri.Public())
	if err != nil {
		return
	}
	pubBlock, err = x509.EncryptPEMBlock(rand.Reader, "RSA PUBLIC KEY", pubbyte, []byte{}, x509.PEMCipherAES256)
	if err != nil {
		return
	}
	//private key encoding

	pribyte := x509.MarshalPKCS1PrivateKey(pri)
	priBlock, err = x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", pribyte, encodepasspharse, x509.PEMCipherAES256)

	return
}
Пример #16
0
// AEStoEncryptedPEM encapsulates an AES key in the encrypted PEM format
func AEStoEncryptedPEM(raw []byte, pwd []byte) ([]byte, error) {
	block, err := x509.EncryptPEMBlock(
		rand.Reader,
		"AES PRIVATE KEY",
		raw,
		pwd,
		x509.PEMCipherAES256)

	if err != nil {
		return nil, err
	}

	return pem.EncodeToMemory(block), nil
}
Пример #17
0
func GenerateECDSAKeyPair(keysize int, password string) (public, private []byte, err error) {
	var curve elliptic.Curve
	switch keysize {
	case 256:
		curve = elliptic.P256()
	case 384:
		curve = elliptic.P384()
	case 521:
		curve = elliptic.P521()
	default:
		return
	}

	// Generate the public/private key pair
	prvKey, err := ecdsa.GenerateKey(curve, rand.Reader)
	if err != nil {
		return
	}

	// Marshal the public key
	sshPubKey, err := ssh.NewPublicKey(&prvKey.PublicKey)
	if err != nil {
		return
	}
	public = ssh.MarshalAuthorizedKey(sshPubKey)

	// Marshal the private key
	prvKeyDer, err := x509.MarshalECPrivateKey(prvKey)
	if err != nil {
		return
	}
	block := &pem.Block{Type: "EC PRIVATE KEY", Bytes: prvKeyDer}

	// Encrypt the private key
	if len(password) != 0 {
		// AES-128 is the only option for private key encryption just like in ssh-keygen.
		block, err = x509.EncryptPEMBlock(rand.Reader,
			"EC PRIVATE KEY",
			prvKeyDer,
			[]byte(password),
			x509.PEMCipherAES128)
		if err != nil {
			return
		}
	}

	private = pem.EncodeToMemory(block)
	return
}
Пример #18
0
func main() {

	secretMsg, err := ioutil.ReadFile("cert2.pem")
	if err != nil {
		fmt.Printf("ReadFile: %s\n", err)
		os.Exit(1)
	}

	blockType := "ENCRYPTED PRIVATE KEY"
	password := []byte("password")

	// see http://golang.org/pkg/crypto/x509/#pkg-constants
	cipherType := x509.PEMCipherAES128

	EncryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
		blockType,
		[]byte(secretMsg),
		password,
		cipherType)

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	sDec := base64.StdEncoding.EncodeToString(EncryptedPEMBlock.Bytes)
	bs := len(sDec)

	// fmt.Printf("raw[%d]:\n%q\n", bs, sDec)
	fmt.Printf("-----BEGIN %s-----\n", blockType)
	for k, v := range EncryptedPEMBlock.Headers {
		fmt.Printf("%s: %s\n", k, v)
	}
	fmt.Printf("\n")

	nblks := bs / 64
	rem := bs % 64

	// fmt.Printf("nBlks = %d, rem = %d\n", nblks, rem)

	for i := 0; i < nblks; i++ {
		fmt.Printf("%s\n", sDec[i*64:(i+1)*64])
	}

	// write the remaining bs-((nblks)*64)
	fmt.Printf("%s\n", sDec[bs-rem:])

	fmt.Printf("-----END %s-----\n", blockType)
}
Пример #19
0
func (crtkit *CertKit) GenerateClient(subject pkix.Name, email, password string) ([]byte, []byte, error) {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, errors.New(fmt.Sprintf("failed to generate private key: %s", err))
	}

	notBefore := time.Now()
	serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
	if err != nil {
		return nil, nil, errors.New(fmt.Sprintf("failed to generate serial number: %s", err))
	}

	template := x509.Certificate{
		SerialNumber:   serialNumber,
		Subject:        subject,
		NotBefore:      notBefore,
		NotAfter:       notBefore.Add(3650 * 24 * time.Hour),
		EmailAddresses: []string{email},
		KeyUsage:       x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:    []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
		UnknownExtKeyUsage: []asn1.ObjectIdentifier{
			[]int{1, 3, 6, 1, 4, 1, 311, 20, 2, 2},  // SmartCard Logon
			[]int{1, 3, 6, 1, 4, 1, 311, 10, 3, 16}, // Verify signature for nonrepudiation?
			//'1.3.6.1.4.1.311.10.3.1' => 'certTrustListSigning'
			// '1.3.6.1.4.1.311.10.3.12' => 'szOID_KP_DOCUMENT_SIGNING',
		},
		BasicConstraintsValid: true,
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, crtkit.CACert, &priv.PublicKey, crtkit.CAKey)
	if err != nil {
		return nil, nil, errors.New(fmt.Sprintf("Failed to create certificate: %s", err))
	}

	certOut := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})

	crypt_priv, err := x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", x509.MarshalPKCS1PrivateKey(priv), []byte(password), x509.PEMCipher3DES)
	if err != nil {
		return nil, nil, errors.New(fmt.Sprintf("Failed to encrypt: %s", err))
	}

	keyOut := pem.EncodeToMemory(crypt_priv)

	return certOut, keyOut, nil
}
Пример #20
0
// ExportEncryptedPrivate exports encrypted PEM-format private key
func (k *Key) ExportEncryptedPrivate(password []byte) ([]byte, error) {
	var privBytes []byte
	switch priv := k.Private.(type) {
	case *rsa.PrivateKey:
		privBytes = x509.MarshalPKCS1PrivateKey(priv)
	default:
		return nil, errors.New("only RSA private key is supported")
	}

	privPEMBlock, err := x509.EncryptPEMBlock(rand.Reader, rsaPrivateKeyPEMBlockType, privBytes, password, x509.PEMCipher3DES)
	if err != nil {
		return nil, err
	}

	buf := new(bytes.Buffer)
	if err := pem.Encode(buf, privPEMBlock); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #21
0
func EncryptPemBlock(block *pem.Block, password string, alg x509.PEMCipher) error {
	if 0 != len(password) {
		if x509.PEMCipher(0) == alg {
			alg = x509.PEMCipherAES256
		}
		newBlock, err := x509.EncryptPEMBlock(rand.Reader, block.Type, block.Bytes, []byte(password), alg)
		if nil != err {
			return err
		}
		if nil == block.Headers {
			block.Headers = newBlock.Headers
		} else {
			for hdr, val := range newBlock.Headers {
				block.Headers[hdr] = val
			}
		}
		block.Bytes = newBlock.Bytes
	}
	return nil
}
Пример #22
0
// EncryptPrivateKey returns an encrypted PEM key given a Privatekey
// and a passphrase
func EncryptPrivateKey(key data.PrivateKey, passphrase string) ([]byte, error) {
	blockType, err := blockType(key.Algorithm())
	if err != nil {
		return nil, err
	}

	password := []byte(passphrase)
	cipherType := x509.PEMCipherAES256

	encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
		blockType,
		key.Private(),
		password,
		cipherType)
	if err != nil {
		return nil, err
	}

	return pem.EncodeToMemory(encryptedPEMBlock), nil
}
Пример #23
0
// EncryptPrivateKey returns an encrypted PEM key given a Privatekey
// and a passphrase
func EncryptPrivateKey(key *data.PrivateKey, passphrase string) ([]byte, error) {
	// TODO(diogo): Currently only supports RSA Private keys
	if key.Cipher() != "RSA" {
		return nil, errors.New("only RSA keys are currently supported")
	}

	password := []byte(passphrase)
	cipherType := x509.PEMCipherAES256
	blockType := "RSA PRIVATE KEY"

	encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
		blockType,
		key.Private(),
		password,
		cipherType)
	if err != nil {
		return nil, err
	}

	return pem.EncodeToMemory(encryptedPEMBlock), nil
}
Пример #24
0
// AEStoEncryptedPEM encapsulates an AES key in the encrypted PEM format
func AEStoEncryptedPEM(raw []byte, pwd []byte) ([]byte, error) {
	if len(raw) == 0 {
		return nil, errors.New("Invalid aes key. It must be different from nil")
	}
	if len(pwd) == 0 {
		return AEStoPEM(raw), nil
	}

	block, err := x509.EncryptPEMBlock(
		rand.Reader,
		"AES PRIVATE KEY",
		raw,
		pwd,
		x509.PEMCipherAES256)

	if err != nil {
		return nil, err
	}

	return pem.EncodeToMemory(block), nil
}
func generatePEM(randReader io.Reader, password []byte) (buf *bytes.Buffer, err error) {
	k, err := rsa.GenerateKey(randReader, 1024)
	if err != nil {
		return nil, err
	}

	derBytes := x509.MarshalPKCS1PrivateKey(k)

	var block *pem.Block
	if password != nil {
		block, err = x509.EncryptPEMBlock(randReader, "RSA PRIVATE KEY", derBytes, password, x509.PEMCipherAES128)
	} else {
		block = &pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: derBytes,
		}
	}

	buf = &bytes.Buffer{}
	err = pem.Encode(buf, block)
	return buf, err
}
Пример #26
0
// EncryptPrivateKey returns an encrypted PEM encoded key given a Private key
// and a passphrase
func EncryptPrivateKey(key crypto.PrivateKey, passphrase string) ([]byte, error) {
	rsaKey, ok := key.(*rsa.PrivateKey)
	if !ok {
		return nil, errors.New("only RSA keys are currently supported")
	}

	keyBytes := x509.MarshalPKCS1PrivateKey(rsaKey)

	password := []byte(passphrase)
	cipherType := x509.PEMCipherAES256
	blockType := "RSA PRIVATE KEY"

	encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
		blockType,
		keyBytes,
		password,
		cipherType)
	if err != nil {
		return nil, err
	}

	return pem.EncodeToMemory(encryptedPEMBlock), nil
}
Пример #27
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
}
Пример #28
0
// Download an encrypted key in PEM format
func (c Project) DownloadEncryptedKey(id, certId int, newKey, existingKey string) revel.Result {
	var user *models.User
	if c.RenderArgs["user"] == nil {
		c.Flash.Error("You must log in first")
		return c.Redirect(routes.App.Index())
	}

	user = c.RenderArgs["user"].(*models.User)

	project := c.getProject(id)
	if project == nil {
		c.Flash.Error("Unable to load project")
		return c.Redirect(routes.App.Index())
	}
	cert := c.getCert(certId)

	if cert == nil {
		c.Flash.Error("Unable to load certificate")
		return c.Redirect(routes.App.Index())
	}

	cert_owners := c.getCertificateOwners(certId)
	project_owners := c.getProjectOwners(id)
	owns := false
	for _, owner := range cert_owners {
		if owner.Id == user.Id {
			owns = true
		}
	}
	for _, owner := range project_owners {
		if owner.Id == user.Id {
			owns = true
		}
	}
	if !user.IsAdmin || !owns {
		c.Flash.Error("You do not have permissions to download the key")
		return c.Redirect(routes.Project.Index(project.Id))

	}

	block, _ := pem.Decode(cert.PrivateKey)
	if block == nil {
		c.Flash.Error("Unable to decode certificate")
		return c.Redirect(routes.Project.Index(project.Id))
	}
	bytes := block.Bytes
	var err error
	// Need to decrypt if the key stored in the database is encrypted
	if len(existingKey) != 0 {
		bytes, err = x509.DecryptPEMBlock(block, []byte(existingKey))
		if err != nil {
			c.Flash.Error("Error decrypting initial key")
			return c.Redirect(routes.Project.Index(project.Id))
		}
	}
	var keyType string
	switch cert.KeyType {
	case models.RSA:
		keyType = "RSA PRIVATE KEY"
	case models.ECDSA:
		keyType = "EC PRIVATE KEY"
	}

	pemKeyBlock := &pem.Block{Type: keyType, Bytes: bytes}
	if len(newKey) > 0 {
		pemKeyBlock, err = x509.EncryptPEMBlock(rand.Reader, pemKeyBlock.Type, pemKeyBlock.Bytes, []byte(newKey), x509.PEMCipherAES256)
		if err != nil {
			c.Flash.Error("Error encrypting key")
			return c.Redirect(routes.Project.Index(project.Id))
		}
	} else {
		c.Flash.Error("Need valid encryption key")
		return c.Redirect(routes.Project.Index(project.Id))
	}
	privCert := pem.EncodeToMemory(pemKeyBlock)

	return Download(privCert)
}
Пример #29
0
// NewOnDiskPBEKeys creates a new Keys structure with the specified key types
// store under PBE on disk. If keys are generated and name is not nil, then a
// self-signed x509 certificate will be generated and saved as well.
func NewOnDiskPBEKeys(keyTypes KeyType, password []byte, path string, name *pkix.Name) (*Keys, error) {
	if keyTypes == 0 || (keyTypes & ^Signing & ^Crypting & ^Deriving != 0) {
		return nil, newError("bad key type")
	}

	if path == "" {
		return nil, newError("bad init call: no path for keys")
	}

	k := &Keys{
		keyTypes: keyTypes,
		dir:      path,
	}

	if len(password) == 0 {
		// This means there's no secret information: just load a public
		// verifying key.
		if k.keyTypes & ^Signing != 0 {
			return nil, newError("without a password, only a verifying key can be loaded")
		}

		err := k.loadCert()
		if err != nil {
			return nil, err
		}
		if k.Cert == nil {
			return nil, newError("no password and can't load cert: %s", k.X509Path())
		}

		if k.VerifyingKey, err = FromX509(k.Cert); err != nil {
			return nil, err
		}
	} else {
		// There are two different types of keysets: in one there's
		// just a Signer, so we use an encrypted PEM format. In the
		// other, there are multiple keys, so we use a custom protobuf
		// format.
		if k.keyTypes & ^Signing != 0 {
			// Check to see if there are already keys.
			f, err := os.Open(k.PBEKeysetPath())
			if err == nil {
				defer f.Close()
				ks, err := ioutil.ReadAll(f)
				if err != nil {
					return nil, err
				}

				data, err := PBEDecrypt(ks, password)
				if err != nil {
					return nil, err
				}
				defer ZeroBytes(data)

				var cks CryptoKeyset
				if err = proto.Unmarshal(data, &cks); err != nil {
					return nil, err
				}

				// TODO(tmroeder): defer zeroKeyset(&cks)

				ktemp, err := UnmarshalKeyset(&cks)
				if err != nil {
					return nil, err
				}

				// Note that this loads the certificate if it's
				// present, and it returns nil otherwise.
				err = k.loadCert()
				if err != nil {
					return nil, err
				}

				k.SigningKey = ktemp.SigningKey
				k.VerifyingKey = ktemp.VerifyingKey
				k.CryptingKey = ktemp.CryptingKey
				k.DerivingKey = ktemp.DerivingKey
			} else {
				// Create and store a new set of keys.
				k, err = NewTemporaryKeys(keyTypes)
				if err != nil {
					return nil, err
				}

				k.dir = path

				cks, err := MarshalKeyset(k)
				if err != nil {
					return nil, err
				}

				// TODO(tmroeder): defer zeroKeyset(cks)

				m, err := proto.Marshal(cks)
				if err != nil {
					return nil, err
				}
				defer ZeroBytes(m)

				enc, err := PBEEncrypt(m, password)
				if err != nil {
					return nil, err
				}

				if err = util.WritePath(k.PBEKeysetPath(), enc, 0777, 0600); err != nil {
					return nil, err
				}

				if k.SigningKey != nil && name != nil {
					err = k.newCert(name)
					if err != nil {
						return nil, err
					}
				}
			}
		} else {
			// There's just a signer, so do PEM encryption of the encoded key.
			f, err := os.Open(k.PBESignerPath())
			if err == nil {
				defer f.Close()
				// Read the signer.
				ss, err := ioutil.ReadAll(f)
				if err != nil {
					return nil, err
				}

				pb, rest := pem.Decode(ss)
				if pb == nil || len(rest) > 0 {
					return nil, newError("decoding failure")
				}

				p, err := x509.DecryptPEMBlock(pb, password)
				if err != nil {
					return nil, err
				}
				defer ZeroBytes(p)

				err = k.loadCert()
				if err != nil {
					return nil, err
				}

				if k.SigningKey, err = UnmarshalSignerDER(p); err != nil {
					return nil, err
				}
				k.VerifyingKey = k.SigningKey.GetVerifier()
			} else {
				// Create a fresh key and store it to the PBESignerPath.
				if k.SigningKey, err = GenerateSigner(); err != nil {
					return nil, err
				}

				k.VerifyingKey = k.SigningKey.GetVerifier()
				p, err := MarshalSignerDER(k.SigningKey)
				if err != nil {
					return nil, err
				}
				defer ZeroBytes(p)

				pb, err := x509.EncryptPEMBlock(rand.Reader, "EC PRIVATE KEY", p, password, x509.PEMCipherAES128)
				if err != nil {
					return nil, err
				}

				pbes, err := util.CreatePath(k.PBESignerPath(), 0777, 0600)
				if err != nil {
					return nil, err
				}
				defer pbes.Close()

				if err = pem.Encode(pbes, pb); err != nil {
					return nil, err
				}

				if k.SigningKey != nil && name != nil {
					err = k.newCert(name)
					if err != nil {
						return nil, err
					}
				}
			}
		}
	}

	return k, nil
}
Пример #30
0
func main() {
	flag.Parse()

	if *printVersion {
		fmt.Println("Quickcert v" + version)
		fmt.Println("https://github.com/andmarios/quickcert")
		os.Exit(0)
	}

	if len(*host) == 0 && !*isCA {
		fmt.Println("If you are not creating a CA pair, you need to set the -hosts parameter. Use -h for help.")
		os.Exit(1)
	}

	var cacert *x509.Certificate
	var cacertpem *pem.Block
	var cakey interface{}
	var err error

	// If not CA, read the CA key and cert
	if !*isCA {
		// Read CAcert
		log.Println("Reading CA certificate")
		data, err := readDecodePemFile(*CAcertFile)
		checkError("Could not read ca key file: ", err)
		cacert, err = x509.ParseCertificate(data.Bytes)
		checkError("Could not parse CA certificate: ", err)
		cacertpem = data

		// Read CAkey
		log.Println("Reading CA private key")
		data, err = readDecodePemFile(*CAkeyFile)
		checkError("Could not read ca key file: ", err)

		// If encrypted, decrypt it
		if x509.IsEncryptedPEMBlock(data) {
			password, err := readPassword("CA key is encrypted\nEnter password: "******"Error reading CA private key password: "******"Could not decrypt CA private key: ", err)
		}

		// Detect type and parse key
		if data.Type == "RSA PRIVATE KEY" {
			cakey, err = x509.ParsePKCS1PrivateKey(data.Bytes)
			checkError("Could not parse CA RSA private key: ", err)
		} else if data.Type == "EC PRIVATE KEY" {
			cakey, err = x509.ParseECPrivateKey(data.Bytes)
			checkError("Could not parse CA ECDSA key: ", err)
		} else {
			log.Fatalf("Could not find a compatible private key type (%s), only RSA and ECDSA are accepted", data.Type)
		}
	}

	// Create new key
	log.Println("Generating private key. This may take some time, depending on type and length.")
	var privkey interface{}
	switch *ecdsaCurve {
	case "":
		if *rsaBits < 2048 && !*isCA {
			log.Println("Consider upgrading your key to 2048 bits or better.")
		} else if *rsaBits < 4096 && *isCA {
			log.Println("Consider upgrading your CA key 4096 bits.")
		}
		privkey, err = rsa.GenerateKey(rand.Reader, *rsaBits)
		// I disabled P224 curve because Redhat patched their golang to
		// not support this curve due to patent law reasons.
		// I could leave it, but then quickcert won't compile on centos, rhel and fedora
		//	case "P224":
		//		privkey, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
	case "P256":
		privkey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	case "P384":
		privkey, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
	case "P521":
		privkey, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
	default:
		log.Fatalf("Unrecognized elliptic curve: %q", *ecdsaCurve)
	}
	checkError("Failed to generate private key: ", err)

	// Create certificate
	log.Println("Generating certificate.")
	var notBefore time.Time
	if len(*validFrom) == 0 {
		notBefore = time.Now()
	} else {
		notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
		checkError("Failed to parse creation date: ", err)
	}

	// time.Duration takes nanoseconds    |--these are nsecs of a day--|
	duration := time.Duration(*validFor * 24 * 3600 * 1000 * 1000 * 1000)
	notAfter := notBefore.Add(duration)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	checkError("Failed to generate serial number: ", err)

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Country:            []string{},
			Organization:       []string{},
			OrganizationalUnit: []string{},
			CommonName:         "",
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
		BasicConstraintsValid: true,
	}
	if len(*cnAttr) > 0 {
		template.Subject.CommonName = *cnAttr
	}
	if len(*cAttr) > 0 {
		template.Subject.Country = append(template.Subject.Country, *cAttr)
	}
	if len(*oAttr) > 0 {
		template.Subject.Organization = append(template.Subject.Organization, *oAttr)
	}
	if len(*ouAttr) > 0 {
		template.Subject.OrganizationalUnit = append(template.Subject.OrganizationalUnit, *ouAttr)
	}

	hosts := strings.Split(*host, ",")
	for _, h := range hosts {
		if ip := net.ParseIP(h); ip != nil {
			template.IPAddresses = append(template.IPAddresses, ip)
		} else {
			template.DNSNames = append(template.DNSNames, h)
		}
	}
	if len(*email) > 0 {
		emails := strings.Split(*email, ",")
		for _, e := range emails {
			template.EmailAddresses = append(template.EmailAddresses, e)
		}
	}

	if *isCA {
		cakey = privkey
		cacert = &template
		template.IsCA = true
		template.KeyUsage |= x509.KeyUsageCertSign
	}

	// Sign certificate
	log.Println("Signing certificate")
	derBytes, err := x509.CreateCertificate(rand.Reader, &template, cacert, publicKey(privkey), cakey)
	checkError("Failed to create certificate: ", err)

	// Check if files to be written exist
	outCrt := *outFile + "crt.pem"
	outKey := *outFile + "key.pem"
	if _, err := os.Stat(outCrt); err == nil {
		checkError("Certificate file exists: ",
			userConfirmation("Certificate file ("+outCrt+") exists. Overwrite? [Yn]: "))
	}
	if _, err := os.Stat(outKey); err == nil {
		checkError("Key file exists: ",
			userConfirmation("Key file ("+outKey+") exists. Overwrite? [Yn]: "))
	}

	// Save certificate to file
	log.Println("Writing certificate file: ", outCrt)
	certOut, err := os.Create(outCrt)
	checkError("Failed to open "+outCrt+" for writing: ", err)
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	if *chain {
		pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: cacertpem.Bytes})
	}
	certOut.Close()

	// Save private key to file
	log.Println("Writing key file: ", outKey)
	keyOut, err := os.OpenFile(outKey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	checkError("Failed to open key.pem for writing:", err)

	keyPemBlock := pemBlockForKey(privkey)
	if *encryptKey {
	ASK_KEY:
		pass1, err := readPassword("Enter password for private key: ")
		checkError("Error reading private key password, attempt 1: ", err)
		pass2, err := readPassword("Please re-enter password for private key: ")
		checkError("Error reading private key password, attempt 2: ", err)
		if string(pass1) == string(pass2) {
			keyPemBlock, err = x509.EncryptPEMBlock(rand.Reader, keyPemBlock.Type, keyPemBlock.Bytes, pass1, x509.PEMCipher3DES)
		} else {
			fmt.Println("Passwords mismatch. Try again.")
			goto ASK_KEY
		}
	}
	pem.Encode(keyOut, keyPemBlock)
	keyOut.Close()

	log.Println("Files written succesfully. Exiting.")
}