mirror of https://github.com/portainer/portainer
feat(libcrypto): move into the Portainer repository EE-5476 (#10230)
parent
9a234204fa
commit
090fa4aeb3
|
@ -8,9 +8,9 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/portainer/libcrypto"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/internal/edge/cache"
|
||||
"github.com/portainer/portainer/pkg/libcrypto"
|
||||
|
||||
"github.com/dchest/uniuri"
|
||||
)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/portainer/libcrypto"
|
||||
"github.com/portainer/portainer/pkg/libcrypto"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -5,10 +5,10 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/portainer/libcrypto"
|
||||
"github.com/portainer/libhttp/response"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/http/client"
|
||||
"github.com/portainer/portainer/pkg/libcrypto"
|
||||
)
|
||||
|
||||
type motdResponse struct {
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/portainer/libcrypto"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
"github.com/portainer/portainer/pkg/libcrypto"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
|
1
go.mod
1
go.mod
|
@ -37,7 +37,6 @@ require (
|
|||
github.com/orcaman/concurrent-map v1.0.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/portainer/libcrypto v0.0.0-20220506221303-1f4fb3b30f9a
|
||||
github.com/portainer/libhttp v0.0.0-20230615144939-a999f666d9a9
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rs/zerolog v1.29.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -311,8 +311,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/portainer/libcrypto v0.0.0-20220506221303-1f4fb3b30f9a h1:B0z3skIMT+OwVNJPQhKp52X+9OWW6A9n5UWig3lHBJk=
|
||||
github.com/portainer/libcrypto v0.0.0-20220506221303-1f4fb3b30f9a/go.mod h1:n54EEIq+MM0NNtqLeCby8ljL+l275VpolXO0ibHegLE=
|
||||
github.com/portainer/libhttp v0.0.0-20230615144939-a999f666d9a9 h1:Jq8g/pDcFL1Z/DnZgn6DyaWu29y9+RiB5aOJ/Xw4960=
|
||||
github.com/portainer/libhttp v0.0.0-20230615144939-a999f666d9a9/go.mod h1:H49JLiywwLt2rrJVroafEWy8fIs0i7mThAThK40sbb8=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
Copyright (c) 2018-2020 Portainer.io
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
|
@ -0,0 +1,3 @@
|
|||
# libcrypto
|
||||
|
||||
A small library providing encryption and decryption functions.
|
|
@ -0,0 +1,35 @@
|
|||
package libcrypto
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Decrypt decrypts data using 256-bit AES-GCM. This both hides the content of
|
||||
// the data and provides a check that it hasn't been altered. Expects input
|
||||
// form nonce|ciphertext|tag where '|' indicates concatenation.
|
||||
// Creates a 32bit hash of the key before decrypting the data.
|
||||
func Decrypt(data []byte, key []byte) ([]byte, error) {
|
||||
hashKey := Hash32Bit(key)
|
||||
|
||||
block, err := aes.NewCipher(hashKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(data) < gcm.NonceSize() {
|
||||
return nil, errors.New("malformed ciphertext")
|
||||
}
|
||||
|
||||
return gcm.Open(nil,
|
||||
data[:gcm.NonceSize()],
|
||||
data[gcm.NonceSize():],
|
||||
nil,
|
||||
)
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package libcrypto
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Encrypt encrypts data using 256-bit AES-GCM. This both hides the content of
|
||||
// the data and provides a check that it hasn't been altered. Output takes the
|
||||
// form nonce|ciphertext|tag where '|' indicates concatenation.
|
||||
// Creates a 32bit hash of the key before encrypting the data.
|
||||
func Encrypt(data, key []byte) ([]byte, error) {
|
||||
hashKey := Hash32Bit(key)
|
||||
|
||||
block, err := aes.NewCipher(hashKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
_, err = io.ReadFull(rand.Reader, nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return gcm.Seal(nonce, nonce, data, nil), nil
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package libcrypto
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
// HashFromBytes returns the hash of the specified data
|
||||
func HashFromBytes(data []byte) []byte {
|
||||
digest := md5.New()
|
||||
digest.Write(data)
|
||||
return digest.Sum(nil)
|
||||
}
|
||||
|
||||
// Hash32Bit returns a hexadecimal encoded hash
|
||||
func Hash32Bit(data []byte) []byte {
|
||||
hash := HashFromBytes(data)
|
||||
return []byte(hex.EncodeToString(hash))
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package libcrypto
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GenerateCertsForHost generates a self-signed certificate for host and saves them at certPath and keyPath
|
||||
func GenerateCertsForHost(hostname, ip, certPath, keyPath string, expiry time.Time) error {
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
NotAfter: expiry,
|
||||
NotBefore: time.Now(),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
|
||||
parsedIP := net.ParseIP(ip)
|
||||
if parsedIP == nil {
|
||||
return errors.New("Failed parsing host ip")
|
||||
}
|
||||
|
||||
template.DNSNames = append(template.DNSNames, hostname)
|
||||
template.IPAddresses = append(template.IPAddresses, parsedIP)
|
||||
|
||||
keyPair, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
encodedCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &keyPair.PublicKey, keyPair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = createPEMEncodedFile(certPath, "CERTIFICATE", encodedCert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key, err := x509.MarshalECPrivateKey(keyPair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = createPEMEncodedFile(keyPath, "EC PRIVATE KEY", key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createPEMEncodedFile(path, header string, data []byte) error {
|
||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
err = pem.Encode(file, &pem.Block{Type: header, Bytes: data})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue