magic.go 3.42 KB
Newer Older
Lukas Matt's avatar
Lukas Matt committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
package federation
//
// GangGo Diaspora Federation Library
// Copyright (C) 2017 Lukas Matt <lukas@zauberstuhl.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

import (
  "encoding/base64"
Lukas Matt's avatar
Lukas Matt committed
22
  "github.com/Zauberstuhl/go-xml"
23 24 25
  "encoding/json"
  "crypto/rsa"
  "crypto/rand"
Lukas Matt's avatar
Lukas Matt committed
26 27
)

Lukas Matt's avatar
Lukas Matt committed
28 29
func MagicEnvelope(privKey *rsa.PrivateKey, handle string, plainXml []byte) (payload []byte, err error) {
  logger.Info("MagicEnvelope with", string(plainXml), "for", handle)
Lukas Matt's avatar
Lukas Matt committed
30 31

  data := base64.URLEncoding.EncodeToString(plainXml)
32
  keyId := base64.URLEncoding.EncodeToString([]byte(handle))
Lukas Matt's avatar
Lukas Matt committed
33

Lukas Matt's avatar
Lukas Matt committed
34
  xmlBody := Message{}
35
  xmlBody.Data.Type = APPLICATION_XML
Lukas Matt's avatar
Lukas Matt committed
36
  xmlBody.Data.Data = data
37 38 39
  xmlBody.Me = XMLNS_ME
  xmlBody.Encoding = BASE64_URL
  xmlBody.Alg = RSA_SHA256
Lukas Matt's avatar
Lukas Matt committed
40 41
  xmlBody.Sig.KeyId = keyId

Lukas Matt's avatar
Lukas Matt committed
42 43 44
  var signature Signature
  err = signature.New(xmlBody).Sign(privKey,
    &(xmlBody.Sig.Sig))
Lukas Matt's avatar
Lukas Matt committed
45
  if err != nil {
46
    logger.Warn(err)
Lukas Matt's avatar
Lukas Matt committed
47 48 49
    return
  }

Lukas Matt's avatar
Lukas Matt committed
50
  payload, err = xml.MarshalIndent(xmlBody, "", "  ")
Lukas Matt's avatar
Lukas Matt committed
51
  if err != nil {
52
    logger.Warn(err)
Lukas Matt's avatar
Lukas Matt committed
53 54
    return
  }
55 56

  logger.Info("MagicEnvelope payload", string(payload))
Lukas Matt's avatar
Lukas Matt committed
57 58
  return
}
59

Lukas Matt's avatar
Lukas Matt committed
60 61
func EncryptedMagicEnvelope(privKey *rsa.PrivateKey, pubKey *rsa.PublicKey, handle string, serializedXml []byte) (payload []byte, err error) {
  logger.Info("EncryptedMagicEnvelope with", string(serializedXml), "for", handle)
62

Lukas Matt's avatar
Lukas Matt committed
63 64
  var aesKeySet Aes
  var aesWrapper AesWrapper
65 66 67
  data := base64.URLEncoding.EncodeToString(serializedXml)
  keyId := base64.URLEncoding.EncodeToString([]byte(handle))

Lukas Matt's avatar
Lukas Matt committed
68
  envelope := Message{
69 70 71 72
    Me: XMLNS_ME,
    Encoding: BASE64_URL,
    Alg: RSA_SHA256,
  }
Lukas Matt's avatar
Lukas Matt committed
73 74 75
  envelope.Data.Type = APPLICATION_XML
  envelope.Data.Data = data
  envelope.Sig.KeyId = keyId
76

Lukas Matt's avatar
Lukas Matt committed
77 78 79
  var signature Signature
  err = signature.New(envelope).Sign(privKey,
    &(envelope.Sig.Sig))
80
  if err != nil {
81
    logger.Warn(err)
82 83 84 85 86 87
    return
  }

  // Generate a new AES key pair
  err = aesKeySet.Generate()
  if err != nil {
88
    logger.Warn(err)
89 90 91
    return
  }

Lukas Matt's avatar
Lukas Matt committed
92
  // payload with aes encryption
Lukas Matt's avatar
Lukas Matt committed
93
  payload, err = xml.MarshalIndent(envelope, "", "  ")
94
  if err != nil {
95
    logger.Warn(err)
96 97 98
    return
  }

99 100 101 102
  logger.Info(
    "EncryptedMagicEnvelope payload with aes encryption",
    string(payload),
  )
Lukas Matt's avatar
Lukas Matt committed
103

104 105
  err = aesKeySet.Encrypt(payload)
  if err != nil {
106
    logger.Warn(err)
107 108 109 110
    return
  }
  aesWrapper.MagicEnvelope = aesKeySet.Data

Lukas Matt's avatar
Lukas Matt committed
111
  // aes with rsa encryption
Lukas Matt's avatar
Lukas Matt committed
112
  aesKeySetXml, err := json.MarshalIndent(aesKeySet, "", "  ")
113
  if err != nil {
114
    logger.Warn(err)
115 116 117
    return
  }

118
  logger.Info("AES key-set XML", string(aesKeySetXml))
119 120 121

  aesKey, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, aesKeySetXml)
  if err != nil {
122
    logger.Warn(err)
123 124 125 126
    return
  }
  aesWrapper.AesKey = base64.StdEncoding.EncodeToString(aesKey)

Lukas Matt's avatar
Lukas Matt committed
127
  payload, err = json.MarshalIndent(aesWrapper, "", "  ")
128
  if err != nil {
129
    logger.Warn(err)
130 131 132
    return
  }

133
  logger.Info("EncryptedMagicEnvelope payload", string(payload))
134 135
  return
}