Skip to content

Instantly share code, notes, and snippets.

@revolunet
Created August 5, 2020 08:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save revolunet/b939997ed6e115c6b4412c904a3cc37d to your computer and use it in GitHub Desktop.
Save revolunet/b939997ed6e115c6b4412c904a3cc37d to your computer and use it in GitHub Desktop.
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rsa"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"io"
"bytes"
"crypto/rand"
"encoding/base64"
"golang.org/x/crypto/ssh"
ssv1alpha1 "github.com/bitnami-labs/sealed-secrets/pkg/apis/sealed-secrets/v1alpha1"
)
const (
sessionKeyBytes = 32
)
func encryptSecretItem(w io.Writer, secretName, ns string, data []byte, scope ssv1alpha1.SealingScope, pubKey *rsa.PublicKey) error {
// TODO(mkm): refactor cluster-wide/namespace-wide to an actual enum so we can have a simple flag
// to refer to the scope mode that is not a tuple of booleans.
label := ssv1alpha1.EncryptionLabel(ns, secretName, scope)
out, err := crypto.HybridEncrypt(rand.Reader, pubKey, data, label)
if err != nil {
return err
}
fmt.Fprint(w, base64.StdEncoding.EncodeToString(out))
return nil
}
// HybridEncrypt performs a regular AES-GCM + RSA-OAEP encryption.
// The output bytestring is:
// RSA ciphertext length || RSA ciphertext || AES ciphertext
func HybridEncrypt(rnd io.Reader, pubKey *rsa.PublicKey, plaintext, label []byte) ([]byte, error) {
// Generate a random symmetric key
sessionKey := make([]byte, sessionKeyBytes)
if _, err := io.ReadFull(rnd, sessionKey); err != nil {
return nil, err
}
block, err := aes.NewCipher(sessionKey)
if err != nil {
return nil, err
}
aed, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
// Encrypt symmetric key
rsaCiphertext, err := rsa.EncryptOAEP(sha256.New(), rnd, pubKey, sessionKey, label)
if err != nil {
return nil, err
}
// First 2 bytes are RSA ciphertext length, so we can separate
// all the pieces later.
ciphertext := make([]byte, 2)
binary.BigEndian.PutUint16(ciphertext, uint16(len(rsaCiphertext)))
ciphertext = append(ciphertext, rsaCiphertext...)
// SessionKey is only used once, so zero nonce is ok
zeroNonce := make([]byte, aed.NonceSize())
// Append symmetrically encrypted Secret
ciphertext = aed.Seal(ciphertext, zeroNonce, plaintext, nil)
return ciphertext, nil
}
func main() {
fmt.Println("Hello, playground")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment