woodpecker/shared/crypto/crypto.go
2015-09-29 18:21:17 -07:00

119 lines
2.9 KiB
Go

package crypto
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"io"
"code.google.com/p/go.crypto/ssh"
"github.com/square/go-jose"
)
const (
RSA_BITS = 2048 // Default number of bits in an RSA key
RSA_BITS_MIN = 768 // Minimum number of bits in an RSA key
)
// standard characters allowed in token string.
var chars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
// default token length
var length = 32
// Rand generates a 32-bit random string.
func Rand() string {
b := make([]byte, length)
r := make([]byte, length+(length/4)) // storage for random bytes.
clen := byte(len(chars))
maxrb := byte(256 - (256 % len(chars)))
i := 0
for {
io.ReadFull(rand.Reader, r)
for _, c := range r {
if c >= maxrb {
// Skip this number to avoid modulo bias.
continue
}
b[i] = chars[c%clen]
i++
if i == length {
return string(b)
}
}
}
}
// helper function to generate an RSA Private Key.
func GeneratePrivateKey() (*rsa.PrivateKey, error) {
return rsa.GenerateKey(rand.Reader, RSA_BITS)
}
// helper function that marshalls an RSA Public Key to an SSH
// .authorized_keys format
func MarshalPublicKey(public *rsa.PublicKey) []byte {
private, err := ssh.NewPublicKey(public)
if err != nil {
return []byte{}
}
return ssh.MarshalAuthorizedKey(private)
}
// helper function that marshalls an RSA Private Key to
// a PEM encoded file.
func MarshalPrivateKey(private *rsa.PrivateKey) []byte {
marshaled := x509.MarshalPKCS1PrivateKey(private)
encoded := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Headers: nil, Bytes: marshaled})
return encoded
}
// UnmarshalPrivateKey is a helper function that unmarshals a PEM
// bytes to an RSA Private Key
func UnmarshalPrivateKey(private []byte) *rsa.PrivateKey {
decoded, _ := pem.Decode(private)
parsed, err := x509.ParsePKCS1PrivateKey(decoded.Bytes)
if err != nil {
return nil
}
return parsed
}
// Encrypt encrypts a secret string.
func Encrypt(in, privKey string) (string, error) {
rsaPrivKey, err := decodePrivateKey(privKey)
if err != nil {
return "", err
}
return encrypt(in, &rsaPrivKey.PublicKey)
}
// decodePrivateKey is a helper function that unmarshals a PEM
// bytes to an RSA Private Key
func decodePrivateKey(privateKey string) (*rsa.PrivateKey, error) {
derBlock, _ := pem.Decode([]byte(privateKey))
return x509.ParsePKCS1PrivateKey(derBlock.Bytes)
}
// encrypt encrypts a plaintext variable using JOSE with
// RSA_OAEP and A128GCM algorithms.
func encrypt(text string, pubKey *rsa.PublicKey) (string, error) {
var encrypted string
var plaintext = []byte(text)
// Creates a new encrypter using defaults
encrypter, err := jose.NewEncrypter(jose.RSA_OAEP, jose.A128GCM, pubKey)
if err != nil {
return encrypted, err
}
// Encrypts the plaintext value and serializes
// as a JOSE string.
object, err := encrypter.Encrypt(plaintext)
if err != nil {
return encrypted, err
}
return object.CompactSerialize()
}