Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Commit

Permalink
re-encrypt
Browse files Browse the repository at this point in the history
  • Loading branch information
blankdots committed Nov 3, 2023
1 parent 1a5d356 commit 45a5827
Show file tree
Hide file tree
Showing 12 changed files with 627 additions and 14 deletions.
53 changes: 53 additions & 0 deletions api/grpc/grpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package grpc

import (
"context"
"fmt"
"time"

log "github.com/sirupsen/logrus"

"github.com/neicnordic/sda-download/internal/config"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"

re "github.com/neicnordic/sda-download/internal/reencrypt"
)

// GetNewHeader
func GetNewHeader(oldHeader []byte, publicKey string) ([]byte, error) {

// Set up a connection to the server.
log.Debug("Connect to grpc Server to get new header")
var opts []grpc.DialOption
if config.Config.Grpc.CACert != "" && config.Config.Grpc.ServerNameOverride != "" {
creds, err := credentials.NewClientTLSFromFile(config.Config.Grpc.CACert, config.Config.Grpc.ServerNameOverride)
if err != nil {
log.Fatalf("Failed to create TLS credentials: %v", err)
}
opts = append(opts, grpc.WithTransportCredentials(creds))
} else {
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
}
log.Debugf("grpc connection to: %s:%d", config.Config.Grpc.Host, config.Config.Grpc.Port)
conn, err := grpc.Dial(fmt.Sprintf("%s:%d", config.Config.Grpc.Host, config.Config.Grpc.Port), opts...)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := re.NewReencryptClient(conn)

// Contact the server and print out its response.
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel()
r, err := c.ReencryptHeader(ctx, &re.ReencryptRequest{Oldheader: oldHeader, Publickey: publicKey})
if err != nil {
log.Errorf("could not get the : %v", err)

return nil, err
}
log.Debugf("Reencrypted Header: %s", string(r.GetHeader()))

return r.GetHeader(), nil
}
31 changes: 27 additions & 4 deletions api/sda/sda.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sda

import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"io"
Expand All @@ -12,10 +13,11 @@ import (
"time"

"github.com/gin-gonic/gin"
"github.com/neicnordic/crypt4gh/keys"
"github.com/neicnordic/crypt4gh/model/headers"
"github.com/neicnordic/crypt4gh/streaming"
"github.com/neicnordic/sda-download/api/grpc"
"github.com/neicnordic/sda-download/api/middleware"
"github.com/neicnordic/sda-download/internal/config"
"github.com/neicnordic/sda-download/internal/database"
"github.com/neicnordic/sda-download/internal/storage"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -198,8 +200,15 @@ func Download(c *gin.Context) {
return
}

header := fileDetails.Header

if c.GetHeader("Crypt4gh-Public-Key") != "" {
clientPublicKey := c.GetHeader("Crypt4gh-Public-Key")
header, _ = grpc.GetNewHeader(header, clientPublicKey)
}

// Stitch file and prepare it for streaming
fileStream, err := stitchFile(fileDetails.Header, file, coordinates)
fileStream, err := stitchFile(header, file, coordinates)
if err != nil {
log.Errorf("could not prepare file for streaming, %s", err)
c.String(http.StatusInternalServerError, "file stream error")
Expand All @@ -213,11 +222,13 @@ func Download(c *gin.Context) {
// stitchFile stitches the header and file body together for Crypt4GHReader
// and returns a streamable Reader
var stitchFile = func(header []byte, file io.ReadCloser, coordinates *headers.DataEditListHeaderPacket) (*streaming.Crypt4GHReader, error) {
publicKey, privateKey, _ := generateFreshKeyPair()
newheader, _ := grpc.GetNewHeader(header, publicKey)
log.Debugf("stitching header to file %s for streaming", file)
// Stitch header and file body together
hr := bytes.NewReader(header)
hr := bytes.NewReader(newheader)
mr := io.MultiReader(hr, file)
c4ghr, err := streaming.NewCrypt4GHReader(mr, *config.Config.App.Crypt4GHKey, coordinates)
c4ghr, err := streaming.NewCrypt4GHReader(mr, privateKey, coordinates)
if err != nil {
log.Errorf("failed to create Crypt4GH stream reader, %v", err)

Expand Down Expand Up @@ -285,3 +296,15 @@ var sendStream = func(w http.ResponseWriter, file io.Reader) {

log.Debugf("Sent %d bytes", n)
}

func generateFreshKeyPair() (string, [32]byte, error) {
publicKey, privateKey, err := keys.GenerateKeyPair()
if err != nil {
log.Errorf("Error while generating key pair: %v", err)

return "", [32]byte{}, err
}
log.Debug("Generated a Fresh Keypair")

return base64.StdEncoding.EncodeToString(publicKey[:]), privateKey, nil
}
93 changes: 93 additions & 0 deletions cmd/reencrypt/reencrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package main

import (
"context"
"fmt"
"net"
"strings"

log "github.com/sirupsen/logrus"

"github.com/neicnordic/crypt4gh/keys"
"github.com/neicnordic/crypt4gh/model/headers"
"golang.org/x/crypto/chacha20poly1305"

"github.com/neicnordic/sda-download/internal/config"
"github.com/neicnordic/sda-download/internal/database"
re "github.com/neicnordic/sda-download/internal/reencrypt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

// server struct is used to implement reencrypt.ReEncryptServer.
type server struct {
re.UnimplementedReencryptServer
}

// init is run before main, it sets up configuration and other required things
func init() {
// Load configuration
conf, err := config.NewConfig("reencrypt")
if err != nil {
log.Panicf("configuration loading failed, reason: %v", err)
}
config.Config = *conf

// Connect to database
db, err := database.NewDB(conf.DB)
if err != nil {
log.Panicf("database connection failed, reason: %v", err)
}
defer db.Close()
database.DB = db

}

// ReencryptHeader implements reencrypt.ReEncryptHeader
func (s *server) ReencryptHeader(ctx context.Context, in *re.ReencryptRequest) (*re.ReencryptResponse, error) {
log.Debugf("Received Public key: %v", in.GetPublickey())
log.Debugf("Received previous crypt4gh header: %v", in.GetOldheader())

// working with the base64 data instead of the full armored key is easier
// as it can be sent in both HTTP headers and HTTP body
newReaderPublicKey, err := keys.ReadPublicKey(strings.NewReader("-----BEGIN CRYPT4GH PUBLIC KEY-----\n" + in.GetPublickey() + "\n-----END CRYPT4GH PUBLIC KEY-----\n"))
if err != nil {
return nil, err
}

newReaderPublicKeyList := [][chacha20poly1305.KeySize]byte{}
newReaderPublicKeyList = append(newReaderPublicKeyList, newReaderPublicKey)

log.Debugf("crypt4ghkey: %v", *config.Config.Grpc.Crypt4GHKey)

newheader, err := headers.ReEncryptHeader(in.GetOldheader(), *config.Config.Grpc.Crypt4GHKey, newReaderPublicKeyList)
if err != nil {
return nil, err
}

return &re.ReencryptResponse{Header: newheader}, nil
}

func main() {
lis, err := net.Listen("tcp", fmt.Sprintf("%s:%d", config.Config.Grpc.Host, config.Config.Grpc.Port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}

var opts []grpc.ServerOption
if config.Config.Grpc.ServerCert != "" && config.Config.Grpc.ServerKey != "" {
creds, err := credentials.NewServerTLSFromFile(config.Config.Grpc.ServerCert, config.Config.Grpc.ServerKey)
if err != nil {
log.Fatalf("Failed to generate credentials: %v", err)
}
opts = []grpc.ServerOption{grpc.Creds(creds)}
}

s := grpc.NewServer(opts...)
re.RegisterReencryptServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}

}
20 changes: 19 additions & 1 deletion dev_utils/compose-no-tls.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
services:

db:
command: server /data
container_name: db
Expand Down Expand Up @@ -74,6 +73,25 @@ services:
- "8080:8080"
restart: always

reencrypt:
command: sda-reencrypt
container_name: reencrypt
depends_on:
db:
condition: service_healthy
environment:
- DB_HOST=db
image: neicnordic/sda-download:latest
build:
context: ..
volumes:
- ./config-notls.yaml:/config.yaml
- ./:/dev_utils/
mem_limit: 256m
ports:
- "5051:5051"
restart: always

mockauth:
command:
- /bin/sh
Expand Down
4 changes: 4 additions & 0 deletions dev_utils/config-notls.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ oidc:
# oidc configuration API must have values for "userinfo_endpoint" and "jwks_uri"
configuration:
url: "http://mockauth:8000/.well-known/openid-configuration"

grpc:
host: reencrypt
port: 5051
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ require (
github.com/go-playground/validator/v10 v10.15.2 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/glog v1.1.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
Expand Down Expand Up @@ -69,12 +70,14 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.4.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/crypto v0.14.0
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.31.0
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
Expand Down Expand Up @@ -597,6 +599,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
Expand All @@ -613,6 +617,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
Expand All @@ -624,6 +630,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
Loading

0 comments on commit 45a5827

Please sign in to comment.