Merge branch 'feat/mime-parsing' into 'master'
Feat/mime parsing See merge request ProtonMail/go-pm-crypto!1
This commit is contained in:
commit
94b317f135
27 changed files with 1095 additions and 455 deletions
54
armor.go
54
armor.go
|
|
@ -1,54 +0,0 @@
|
||||||
package pm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp/armor"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
pgpMessageType string = "PGP MESSAGE"
|
|
||||||
pgpPublicBlockType string = "PGP PUBLIC KEY BLOCK"
|
|
||||||
pgpPrivateBlockType string = "PGP PRIVATE KEY BLOCK"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ArmorKey make bytes input key to armor format
|
|
||||||
func ArmorKey(input []byte) (string, error) {
|
|
||||||
return ArmorWithType(input, pgpPublicBlockType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArmorWithType make bytes input to armor format
|
|
||||||
func ArmorWithType(input []byte, armorType string) (string, error) {
|
|
||||||
var b bytes.Buffer
|
|
||||||
w, err := armor.Encode(&b, armorType, armorHeader)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
_, err = w.Write(input)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
w.Close()
|
|
||||||
return b.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnArmor an armored key to bytes key
|
|
||||||
func UnArmor(input string) ([]byte, error) {
|
|
||||||
b, err := unArmor(input)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ioutil.ReadAll(b.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func unArmor(input string) (*armor.Block, error) {
|
|
||||||
io := strings.NewReader(input)
|
|
||||||
b, err := armor.Decode(io)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
129
armor/armor.go
Normal file
129
armor/armor.go
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
package armor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"gitlab.com/ProtonMail/go-pm-crypto/internal"
|
||||||
|
"gitlab.com/ProtonMail/go-pm-crypto/models"
|
||||||
|
"golang.org/x/crypto/openpgp/armor"
|
||||||
|
"golang.org/x/crypto/openpgp/clearsign"
|
||||||
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ArmorKey make bytes input key to armor format
|
||||||
|
func ArmorKey(input []byte) (string, error) {
|
||||||
|
return ArmorWithType(input, PUBLIC_KEY_HEADER)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArmorWithType make bytes input to armor format
|
||||||
|
func ArmorWithType(input []byte, armorType string) (string, error) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
w, err := armor.Encode(&b, armorType, internal.ArmorHeaders)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
_, err = w.Write(input)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
w.Close()
|
||||||
|
return b.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unarmor an armored key to bytes key
|
||||||
|
func Unarmor(input string) ([]byte, error) {
|
||||||
|
b, err := internal.Unarmor(input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ioutil.ReadAll(b.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
//ReadClearSignedMessage read clear message from a clearsign package
|
||||||
|
func ReadClearSignedMessage(signedMessage string) (string, error) {
|
||||||
|
modulusBlock, rest := clearsign.Decode([]byte(signedMessage))
|
||||||
|
if len(rest) != 0 {
|
||||||
|
return "", errors.New("pmapi: extra data after modulus")
|
||||||
|
}
|
||||||
|
return string(modulusBlock.Bytes), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//SeparateKeyAndData ...
|
||||||
|
func SplitArmor(encrypted string) (*models.EncryptedSplit, error) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
encryptedRaw, err := Unarmor(encrypted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptedReader := bytes.NewReader(encryptedRaw)
|
||||||
|
|
||||||
|
//kr *KeyRing, r io.Reader) (key *SymmetricKey, symEncryptedData []byte,
|
||||||
|
packets := packet.NewReader(encryptedReader)
|
||||||
|
|
||||||
|
outSplit := &models.EncryptedSplit{}
|
||||||
|
|
||||||
|
// Save encrypted key and signature apart
|
||||||
|
var ek *packet.EncryptedKey
|
||||||
|
// var decryptErr error
|
||||||
|
for {
|
||||||
|
var p packet.Packet
|
||||||
|
if p, err = packets.Next(); err == io.EOF {
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch p := p.(type) {
|
||||||
|
case *packet.EncryptedKey:
|
||||||
|
// We got an encrypted key. Try to decrypt it with each available key
|
||||||
|
if ek != nil && ek.Key != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ek = p
|
||||||
|
break
|
||||||
|
case *packet.SymmetricallyEncrypted:
|
||||||
|
var packetContents []byte
|
||||||
|
if packetContents, err = ioutil.ReadAll(p.Contents); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
encodedLength := encodedLength(len(packetContents) + 1)
|
||||||
|
var symEncryptedData []byte
|
||||||
|
symEncryptedData = append(symEncryptedData, byte(210))
|
||||||
|
symEncryptedData = append(symEncryptedData, encodedLength...)
|
||||||
|
symEncryptedData = append(symEncryptedData, byte(1))
|
||||||
|
symEncryptedData = append(symEncryptedData, packetContents...)
|
||||||
|
|
||||||
|
outSplit.DataPacket = symEncryptedData
|
||||||
|
break
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
ek.Serialize(&buf)
|
||||||
|
outSplit.KeyPacket = buf.Bytes()
|
||||||
|
|
||||||
|
return outSplit, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//encode length based on 4.2.2. in the RFC
|
||||||
|
func encodedLength(length int) (b []byte) {
|
||||||
|
if length < 192 {
|
||||||
|
b = append(b, byte(length))
|
||||||
|
} else if length < 8384 {
|
||||||
|
length = length - 192
|
||||||
|
b = append(b, 192+byte(length>>8))
|
||||||
|
b = append(b, byte(length))
|
||||||
|
} else {
|
||||||
|
b = append(b, byte(255))
|
||||||
|
b = append(b, byte(length>>24))
|
||||||
|
b = append(b, byte(length>>16))
|
||||||
|
b = append(b, byte(length>>8))
|
||||||
|
b = append(b, byte(length))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
13
armor/constants.go
Normal file
13
armor/constants.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
package armor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitlab.com/ProtonMail/go-pm-crypto/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ARMOR_HEADER_VERSION = internal.ARMOR_HEADER_VERSION
|
||||||
|
ARMOR_HEADER_COMMENT = internal.ARMOR_HEADER_COMMENT
|
||||||
|
MESSAGE_HEADER string = "PGP MESSAGE"
|
||||||
|
PUBLIC_KEY_HEADER string = "PGP PUBLIC KEY BLOCK"
|
||||||
|
PRIVATE_KEY_HEADER string = "PGP PRIVATE KEY BLOCK"
|
||||||
|
)
|
||||||
11
build.sh
11
build.sh
|
|
@ -2,21 +2,20 @@
|
||||||
|
|
||||||
SCRIPT_LOCATION=$(cd $(dirname $0);echo $PWD)
|
SCRIPT_LOCATION=$(cd $(dirname $0);echo $PWD)
|
||||||
|
|
||||||
OUTPUT_PATH="bin"
|
OUTPUT_PATH="dist"
|
||||||
ANDROID_OUT=${OUTPUT_PATH}/"Android"
|
ANDROID_OUT=${OUTPUT_PATH}/"Android"
|
||||||
IOS_OUT=${OUTPUT_PATH}/"iOS"
|
IOS_OUT=${OUTPUT_PATH}/"iOS"
|
||||||
|
mkdir -p $ANDROID_OUT
|
||||||
|
mkdir -p $IOS_OUT
|
||||||
# CHECK="${1-0}"
|
# CHECK="${1-0}"
|
||||||
# if [ ${CHECK} -eq "1" ]; then
|
# if [ ${CHECK} -eq "1" ]; then
|
||||||
printf "\e[0;32mStart Building iOS framework .. Location: ${IOS_OUT} \033[0m\n\n"
|
printf "\e[0;32mStart Building iOS framework .. Location: ${IOS_OUT} \033[0m\n\n"
|
||||||
|
|
||||||
gomobile bind -target ios -o ${IOS_OUT}/PM.framework
|
gomobile bind -target ios -o ${IOS_OUT}/pmcrypto.framework proton/pmcrypto/crypto proton/pmcrypto/armor proton/pmcrypto/constants proton/pmcrypto/key proton/pmcrypto/models
|
||||||
|
|
||||||
|
|
||||||
printf "\e[0;32mStart Building Android lib .. Location: ${ANDROID_OUT} \033[0m\n\n"
|
printf "\e[0;32mStart Building Android lib .. Location: ${ANDROID_OUT} \033[0m\n\n"
|
||||||
|
|
||||||
gomobile bind -target android -o ${ANDROID_OUT}/PM.aar
|
gomobile bind -target android -javapkg com.proton.pmcrypto -o ${ANDROID_OUT}/pmcrypto.aar proton/pmcrypto/crypto proton/pmcrypto/armor proton/pmcrypto/constants proton/pmcrypto/key proton/pmcrypto/models
|
||||||
|
|
||||||
|
|
||||||
printf "\e[0;32mInstalling frameworks. \033[0m\n\n"
|
printf "\e[0;32mInstalling frameworks. \033[0m\n\n"
|
||||||
|
|
||||||
|
|
|
||||||
36
common.go
36
common.go
|
|
@ -1,36 +0,0 @@
|
||||||
package pm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
var armorHeader = map[string]string{
|
|
||||||
"Version": "OpenPGP Golang 0.0.1 (" + Version() + ")",
|
|
||||||
"Comment": "https://protonmail.com",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key ... add later
|
|
||||||
// protonmail key object
|
|
||||||
type Key struct {
|
|
||||||
KeyID string
|
|
||||||
PublicKey string
|
|
||||||
PrivateKey string
|
|
||||||
FingerPrint string
|
|
||||||
}
|
|
||||||
|
|
||||||
//Address ... add later protonmail address object
|
|
||||||
type Address struct {
|
|
||||||
// address_id : string;
|
|
||||||
// #optional
|
|
||||||
// address_name : string;
|
|
||||||
keys []Key
|
|
||||||
}
|
|
||||||
|
|
||||||
func trimNewlines(input string) string {
|
|
||||||
var re = regexp.MustCompile(`(?m)[ \t]*$`)
|
|
||||||
return re.ReplaceAllString(input, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Amount of seconds that a signature may be created after the verify time
|
|
||||||
// Consistent with the 2 day slack allowed in the ProtonMail Email Parser
|
|
||||||
var creationTimeOffset = int64(60 * 60 * 24 * 2)
|
|
||||||
3
constants/version.go
Normal file
3
constants/version.go
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
package constants
|
||||||
|
|
||||||
|
const VERSION = "ddacebe0"
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package pm
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -8,13 +8,16 @@ import (
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
"golang.org/x/crypto/openpgp/armor"
|
"golang.org/x/crypto/openpgp/armor"
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
|
armorUtils "proton/pmcrypto/armor"
|
||||||
|
"proton/pmcrypto/internal"
|
||||||
|
"proton/pmcrypto/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
//EncryptAttachmentBinKey ...
|
//EncryptAttachmentBinKey ...
|
||||||
func (o *OpenPGP) EncryptAttachmentBinKey(plainData []byte, fileName string, publicKey []byte) (*EncryptedSplit, error) {
|
func (pm *PmCrypto) EncryptAttachmentBinKey(plainData []byte, fileName string, publicKey []byte) (*models.EncryptedSplit, error) {
|
||||||
|
|
||||||
var outBuf bytes.Buffer
|
var outBuf bytes.Buffer
|
||||||
w, err := armor.Encode(&outBuf, pgpMessageType, armorHeader)
|
w, err := armor.Encode(&outBuf, armorUtils.MESSAGE_HEADER, internal.ArmorHeaders)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +33,7 @@ func (o *OpenPGP) EncryptAttachmentBinKey(plainData []byte, fileName string, pub
|
||||||
|
|
||||||
config := &packet.Config{
|
config := &packet.Config{
|
||||||
DefaultCipher: packet.CipherAES256,
|
DefaultCipher: packet.CipherAES256,
|
||||||
Time: o.getTimeGenerator(),
|
Time: pm.getTimeGenerator(),
|
||||||
}
|
}
|
||||||
|
|
||||||
ew, err := openpgp.Encrypt(w, pubKeyEntries, nil, hints, config)
|
ew, err := openpgp.Encrypt(w, pubKeyEntries, nil, hints, config)
|
||||||
|
|
@ -39,7 +42,7 @@ func (o *OpenPGP) EncryptAttachmentBinKey(plainData []byte, fileName string, pub
|
||||||
ew.Close()
|
ew.Close()
|
||||||
w.Close()
|
w.Close()
|
||||||
|
|
||||||
split, err := SeparateKeyAndData(outBuf.String())
|
split, err := armorUtils.SplitArmor(outBuf.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -48,19 +51,19 @@ func (o *OpenPGP) EncryptAttachmentBinKey(plainData []byte, fileName string, pub
|
||||||
}
|
}
|
||||||
|
|
||||||
//EncryptAttachment ...
|
//EncryptAttachment ...
|
||||||
func (o *OpenPGP) EncryptAttachment(plainData []byte, fileName string, publicKey string) (*EncryptedSplit, error) {
|
func (pm *PmCrypto) EncryptAttachment(plainData []byte, fileName string, publicKey string) (*models.EncryptedSplit, error) {
|
||||||
rawPubKey, err := UnArmor(publicKey)
|
rawPubKey, err := armorUtils.Unarmor(publicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return o.EncryptAttachmentBinKey(plainData, fileName, rawPubKey)
|
return pm.EncryptAttachmentBinKey(plainData, fileName, rawPubKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
//DecryptAttachmentBinKey ...
|
//DecryptAttachmentBinKey ...
|
||||||
//keyPacket
|
//keyPacket
|
||||||
//dataPacket
|
//dataPacket
|
||||||
//privateKeys could be mutiple private keys
|
//privateKeys could be mutiple private keys
|
||||||
func (o *OpenPGP) DecryptAttachmentBinKey(keyPacket []byte, dataPacket []byte, privateKeys []byte, passphrase string) ([]byte, error) {
|
func (pm *PmCrypto) DecryptAttachmentBinKey(keyPacket []byte, dataPacket []byte, privateKeys []byte, passphrase string) ([]byte, error) {
|
||||||
privKeyRaw := bytes.NewReader(privateKeys)
|
privKeyRaw := bytes.NewReader(privateKeys)
|
||||||
privKeyEntries, err := openpgp.ReadKeyRing(privKeyRaw)
|
privKeyEntries, err := openpgp.ReadKeyRing(privKeyRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -86,7 +89,7 @@ func (o *OpenPGP) DecryptAttachmentBinKey(keyPacket []byte, dataPacket []byte, p
|
||||||
|
|
||||||
encryptedReader := io.MultiReader(keyReader, dataReader)
|
encryptedReader := io.MultiReader(keyReader, dataReader)
|
||||||
|
|
||||||
config := &packet.Config{ Time: o.getTimeGenerator() }
|
config := &packet.Config{Time: pm.getTimeGenerator()}
|
||||||
|
|
||||||
md, err := openpgp.ReadMessage(encryptedReader, privKeyEntries, nil, config)
|
md, err := openpgp.ReadMessage(encryptedReader, privKeyEntries, nil, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -103,24 +106,24 @@ func (o *OpenPGP) DecryptAttachmentBinKey(keyPacket []byte, dataPacket []byte, p
|
||||||
}
|
}
|
||||||
|
|
||||||
//DecryptAttachment ...
|
//DecryptAttachment ...
|
||||||
func (o *OpenPGP) DecryptAttachment(keyPacket []byte, dataPacket []byte, privateKey string, passphrase string) ([]byte, error) {
|
func (pm *PmCrypto) DecryptAttachment(keyPacket []byte, dataPacket []byte, privateKey string, passphrase string) ([]byte, error) {
|
||||||
rawPrivKey, err := UnArmor(privateKey)
|
rawPrivKey, err := armorUtils.Unarmor(privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return o.DecryptAttachmentBinKey(keyPacket, dataPacket, rawPrivKey, passphrase)
|
return pm.DecryptAttachmentBinKey(keyPacket, dataPacket, rawPrivKey, passphrase)
|
||||||
}
|
}
|
||||||
|
|
||||||
//EncryptAttachmentWithPassword ...
|
//EncryptAttachmentWithPassword ...
|
||||||
func (o *OpenPGP) EncryptAttachmentWithPassword(plainData []byte, password string) (string, error) {
|
func (pm *PmCrypto) EncryptAttachmentWithPassword(plainData []byte, password string) (string, error) {
|
||||||
|
|
||||||
var outBuf bytes.Buffer
|
var outBuf bytes.Buffer
|
||||||
w, err := armor.Encode(&outBuf, pgpMessageType, armorHeader)
|
w, err := armor.Encode(&outBuf, armorUtils.MESSAGE_HEADER, internal.ArmorHeaders)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{ Time: o.getTimeGenerator() }
|
config := &packet.Config{Time: pm.getTimeGenerator()}
|
||||||
|
|
||||||
plaintext, err := openpgp.SymmetricallyEncrypt(w, []byte(password), nil, config)
|
plaintext, err := openpgp.SymmetricallyEncrypt(w, []byte(password), nil, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -141,7 +144,7 @@ func (o *OpenPGP) EncryptAttachmentWithPassword(plainData []byte, password strin
|
||||||
}
|
}
|
||||||
|
|
||||||
//DecryptAttachmentWithPassword ...
|
//DecryptAttachmentWithPassword ...
|
||||||
func (o *OpenPGP) DecryptAttachmentWithPassword(keyPacket []byte, dataPacket []byte, password string) ([]byte, error) {
|
func (pm *PmCrypto) DecryptAttachmentWithPassword(keyPacket []byte, dataPacket []byte, password string) ([]byte, error) {
|
||||||
|
|
||||||
encrypted := append(keyPacket, dataPacket...)
|
encrypted := append(keyPacket, dataPacket...)
|
||||||
|
|
||||||
|
|
@ -151,7 +154,7 @@ func (o *OpenPGP) DecryptAttachmentWithPassword(keyPacket []byte, dataPacket []b
|
||||||
return []byte(password), nil
|
return []byte(password), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{ Time: o.getTimeGenerator() }
|
config := &packet.Config{Time: pm.getTimeGenerator()}
|
||||||
|
|
||||||
md, err := openpgp.ReadMessage(encryptedReader, nil, prompt, config)
|
md, err := openpgp.ReadMessage(encryptedReader, nil, prompt, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1,38 +1,19 @@
|
||||||
package pm
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto"
|
"crypto"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"proton/pmcrypto/armor"
|
||||||
)
|
)
|
||||||
|
|
||||||
//EncryptedSplit when encrypt attachemt
|
|
||||||
type EncryptedSplit struct {
|
|
||||||
DataPacket []byte
|
|
||||||
KeyPacket []byte
|
|
||||||
Algo string
|
|
||||||
}
|
|
||||||
|
|
||||||
//SessionSplit splited session
|
|
||||||
type SessionSplit struct {
|
|
||||||
Session []byte
|
|
||||||
Algo string
|
|
||||||
}
|
|
||||||
|
|
||||||
//EncryptedSigned encrypt_sign_package
|
|
||||||
type EncryptedSigned struct {
|
|
||||||
Encrypted string
|
|
||||||
Signature string
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ok = 0
|
ok = 0
|
||||||
notSigned = 1
|
notSigned = 1
|
||||||
|
|
@ -40,49 +21,9 @@ const (
|
||||||
failed = 3
|
failed = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
//DecryptSignedVerify decrypt_sign_verify
|
|
||||||
type DecryptSignedVerify struct {
|
|
||||||
//clear text
|
|
||||||
Plaintext string
|
|
||||||
//bitmask verify status : 0
|
|
||||||
Verify int
|
|
||||||
//error message if verify failed
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
//CheckPassphrase check is private key passphrase ok
|
|
||||||
func CheckPassphrase(privateKey string, passphrase string) bool {
|
|
||||||
privKeyReader := strings.NewReader(privateKey)
|
|
||||||
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var keys []*packet.PrivateKey
|
|
||||||
|
|
||||||
for _, e := range entries {
|
|
||||||
keys = append(keys, e.PrivateKey)
|
|
||||||
}
|
|
||||||
var decryptError error
|
|
||||||
var n int
|
|
||||||
for _, key := range keys {
|
|
||||||
if !key.Encrypted {
|
|
||||||
continue // Key already decrypted
|
|
||||||
}
|
|
||||||
if decryptError = key.Decrypt([]byte(passphrase)); decryptError == nil {
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if n == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
//IsKeyExpiredBin ...
|
//IsKeyExpiredBin ...
|
||||||
func (o *OpenPGP) IsKeyExpiredBin(publicKey []byte) (bool, error) {
|
func (pm *PmCrypto) IsKeyExpiredBin(publicKey []byte) (bool, error) {
|
||||||
now := o.getNow()
|
now := pm.getNow()
|
||||||
pubKeyReader := bytes.NewReader(publicKey)
|
pubKeyReader := bytes.NewReader(publicKey)
|
||||||
pubKeyEntries, err := openpgp.ReadKeyRing(pubKeyReader)
|
pubKeyEntries, err := openpgp.ReadKeyRing(pubKeyReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -134,15 +75,15 @@ func (o *OpenPGP) IsKeyExpiredBin(publicKey []byte) (bool, error) {
|
||||||
|
|
||||||
//IsKeyExpired ....
|
//IsKeyExpired ....
|
||||||
// will user the cached time to check
|
// will user the cached time to check
|
||||||
func (o *OpenPGP) IsKeyExpired(publicKey string) (bool, error) {
|
func (pm *PmCrypto) IsKeyExpired(publicKey string) (bool, error) {
|
||||||
rawPubKey, err := UnArmor(publicKey)
|
rawPubKey, err := armor.Unarmor(publicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return o.IsKeyExpiredBin(rawPubKey)
|
return pm.IsKeyExpiredBin(rawPubKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OpenPGP) generateKey(userName string, domain string, passphrase string, keyType string, bits int,
|
func (pm *PmCrypto) generateKey(userName string, domain string, passphrase string, keyType string, bits int,
|
||||||
prime1 []byte, prime2 []byte, prime3 []byte, prime4 []byte) (string, error) {
|
prime1 []byte, prime2 []byte, prime3 []byte, prime4 []byte) (string, error) {
|
||||||
|
|
||||||
if len(userName) <= 0 {
|
if len(userName) <= 0 {
|
||||||
|
|
@ -159,7 +100,7 @@ func (o *OpenPGP) generateKey(userName string, domain string, passphrase string,
|
||||||
cfg := &packet.Config{
|
cfg := &packet.Config{
|
||||||
Algorithm: packet.PubKeyAlgoRSA,
|
Algorithm: packet.PubKeyAlgoRSA,
|
||||||
RSABits: bits,
|
RSABits: bits,
|
||||||
Time: o.getTimeGenerator(),
|
Time: pm.getTimeGenerator(),
|
||||||
DefaultHash: crypto.SHA256,
|
DefaultHash: crypto.SHA256,
|
||||||
DefaultCipher: packet.CipherAES256,
|
DefaultCipher: packet.CipherAES256,
|
||||||
}
|
}
|
||||||
|
|
@ -191,7 +132,6 @@ func (o *OpenPGP) generateKey(userName string, domain string, passphrase string,
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rawPwd := []byte(passphrase)
|
rawPwd := []byte(passphrase)
|
||||||
if newEntity.PrivateKey != nil && !newEntity.PrivateKey.Encrypted {
|
if newEntity.PrivateKey != nil && !newEntity.PrivateKey.Encrypted {
|
||||||
if err := newEntity.PrivateKey.Encrypt(rawPwd); err != nil {
|
if err := newEntity.PrivateKey.Encrypt(rawPwd); err != nil {
|
||||||
|
|
@ -212,12 +152,12 @@ func (o *OpenPGP) generateKey(userName string, domain string, passphrase string,
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
serialized := w.Bytes()
|
serialized := w.Bytes()
|
||||||
return ArmorWithType(serialized, pgpPrivateBlockType)
|
return armor.ArmorWithType(serialized, armor.PRIVATE_KEY_HEADER)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OpenPGP) GenerateRSAKeyWithPrimes(userName string, domain string, passphrase string, bits int,
|
func (pm *PmCrypto) GenerateRSAKeyWithPrimes(userName string, domain string, passphrase string, bits int,
|
||||||
primeone []byte, primetwo []byte, primethree []byte, primefour []byte) (string, error) {
|
primeone []byte, primetwo []byte, primethree []byte, primefour []byte) (string, error) {
|
||||||
return o.generateKey(userName, domain, passphrase, "rsa", bits, primeone, primetwo, primethree, primefour)
|
return pm.generateKey(userName, domain, passphrase, "rsa", bits, primeone, primetwo, primethree, primefour)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateKey ...
|
// GenerateKey ...
|
||||||
|
|
@ -226,11 +166,12 @@ func (o *OpenPGP) GenerateRSAKeyWithPrimes(userName string, domain string, passp
|
||||||
// #static generate_key_with_email(email : string, passphrase : string, bits : i32) : open_pgp_key;
|
// #static generate_key_with_email(email : string, passphrase : string, bits : i32) : open_pgp_key;
|
||||||
// # generate new key
|
// # generate new key
|
||||||
// #static generate_new_key(user_id : string, email : string, passphrase : string, bits : i32) : open_pgp_key;
|
// #static generate_new_key(user_id : string, email : string, passphrase : string, bits : i32) : open_pgp_key;
|
||||||
func (o *OpenPGP) GenerateKey(userName string, domain string, passphrase string, keyType string, bits int) (string, error) {
|
func (pm *PmCrypto) GenerateKey(userName string, domain string, passphrase string, keyType string, bits int) (string, error) {
|
||||||
return o.generateKey(userName, domain, passphrase, keyType, bits, nil, nil, nil, nil)
|
return pm.generateKey(userName, domain, passphrase, keyType, bits, nil, nil, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePrivateKeyPassphrase ...
|
// UpdatePrivateKeyPassphrase ...
|
||||||
func (o *OpenPGP) UpdatePrivateKeyPassphrase(privateKey string, oldPassphrase string, newPassphrase string) (string, error) {
|
func (pm *PmCrypto) UpdatePrivateKeyPassphrase(privateKey string, oldPassphrase string, newPassphrase string) (string, error) {
|
||||||
|
|
||||||
privKey := strings.NewReader(privateKey)
|
privKey := strings.NewReader(privateKey)
|
||||||
privKeyEntries, err := openpgp.ReadArmoredKeyRing(privKey)
|
privKeyEntries, err := openpgp.ReadArmoredKeyRing(privKey)
|
||||||
|
|
@ -271,48 +212,11 @@ func (o *OpenPGP) UpdatePrivateKeyPassphrase(privateKey string, oldPassphrase st
|
||||||
}
|
}
|
||||||
|
|
||||||
serialized := w.Bytes()
|
serialized := w.Bytes()
|
||||||
return ArmorWithType(serialized, pgpPrivateBlockType)
|
return armor.ArmorWithType(serialized, armor.PRIVATE_KEY_HEADER)
|
||||||
}
|
|
||||||
|
|
||||||
// PublicKey get a public key from a private key
|
|
||||||
func PublicKey(privateKey string) (string, error) {
|
|
||||||
privKeyReader := strings.NewReader(privateKey)
|
|
||||||
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
var outBuf bytes.Buffer
|
|
||||||
for _, e := range entries {
|
|
||||||
e.Serialize(&outBuf)
|
|
||||||
}
|
|
||||||
|
|
||||||
outString, err := ArmorWithType(outBuf.Bytes(), pgpPublicBlockType)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return outString, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PublicKeyBinOut get a public key from a private key
|
|
||||||
func PublicKeyBinOut(privateKey string) ([]byte, error) {
|
|
||||||
privKeyReader := strings.NewReader(privateKey)
|
|
||||||
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var outBuf bytes.Buffer
|
|
||||||
for _, e := range entries {
|
|
||||||
e.Serialize(&outBuf)
|
|
||||||
}
|
|
||||||
|
|
||||||
return outBuf.Bytes(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckKey print out the key and subkey fingerprint
|
// CheckKey print out the key and subkey fingerprint
|
||||||
func CheckKey(pubKey string) (string, error) {
|
func (pm *PmCrypto) CheckKey(pubKey string) (string, error) {
|
||||||
pubKeyReader := strings.NewReader(pubKey)
|
pubKeyReader := strings.NewReader(pubKey)
|
||||||
entries, err := openpgp.ReadArmoredKeyRing(pubKeyReader)
|
entries, err := openpgp.ReadArmoredKeyRing(pubKeyReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package pm
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -10,35 +10,38 @@ import (
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
"golang.org/x/crypto/openpgp/armor"
|
"golang.org/x/crypto/openpgp/armor"
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
|
||||||
errors2 "golang.org/x/crypto/openpgp/errors"
|
errors2 "golang.org/x/crypto/openpgp/errors"
|
||||||
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
"math"
|
"math"
|
||||||
|
armorUtils "proton/pmcrypto/armor"
|
||||||
|
"proton/pmcrypto/internal"
|
||||||
|
"proton/pmcrypto/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DecryptMessage decrypt encrypted message use private key (string )
|
// DecryptMessage decrypt encrypted message use private key (string )
|
||||||
// encryptedText : string armored encrypted
|
// encryptedText : string armored encrypted
|
||||||
// privateKey : armored private use to decrypt message
|
// privateKey : armored private use to decrypt message
|
||||||
// passphrase : match with private key to decrypt message
|
// passphrase : match with private key to decrypt message
|
||||||
func (o *OpenPGP) DecryptMessage(encryptedText string, privateKey string, passphrase string) (string, error) {
|
func (pm *PmCrypto) DecryptMessage(encryptedText string, privateKey string, passphrase string) (string, error) {
|
||||||
privKeyRaw, err := UnArmor(privateKey)
|
privKeyRaw, err := armorUtils.Unarmor(privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return o.DecryptMessageBinKey(encryptedText, privKeyRaw, passphrase)
|
return pm.DecryptMessageBinKey(encryptedText, privKeyRaw, passphrase)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptMessageBinKey decrypt encrypted message use private key (bytes )
|
// DecryptMessageBinKey decrypt encrypted message use private key (bytes )
|
||||||
// encryptedText : string armored encrypted
|
// encryptedText : string armored encrypted
|
||||||
// privateKey : unarmored private use to decrypt message could be mutiple keys
|
// privateKey : unarmored private use to decrypt message could be mutiple keys
|
||||||
// passphrase : match with private key to decrypt message
|
// passphrase : match with private key to decrypt message
|
||||||
func (o *OpenPGP) DecryptMessageBinKey(encryptedText string, privateKey []byte, passphrase string) (string, error) {
|
func (pm *PmCrypto) DecryptMessageBinKey(encryptedText string, privateKey []byte, passphrase string) (string, error) {
|
||||||
privKey := bytes.NewReader(privateKey)
|
privKey := bytes.NewReader(privateKey)
|
||||||
privKeyEntries, err := openpgp.ReadKeyRing(privKey)
|
privKeyEntries, err := openpgp.ReadKeyRing(privKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedio, err := unArmor(encryptedText)
|
encryptedio, err := internal.Unarmor(encryptedText)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +59,7 @@ func (o *OpenPGP) DecryptMessageBinKey(encryptedText string, privateKey []byte,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{ Time: o.getTimeGenerator() }
|
config := &packet.Config{Time: pm.getTimeGenerator()}
|
||||||
|
|
||||||
md, err := openpgp.ReadMessage(encryptedio.Body, privKeyEntries, nil, config)
|
md, err := openpgp.ReadMessage(encryptedio.Body, privKeyEntries, nil, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -73,57 +76,57 @@ func (o *OpenPGP) DecryptMessageBinKey(encryptedText string, privateKey []byte,
|
||||||
return string(b), nil
|
return string(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptMessageVerifyPrivbinkeys decrypt message and verify the signature
|
// DecryptMessageVerifyPrivBinKeys decrypt message and verify the signature
|
||||||
// veriferKey string: armored verifier keys
|
// verifierKey string: armored verifier keys
|
||||||
// privateKey []byte: unarmored private key to decrypt. could be mutiple
|
// privateKey []byte: unarmored private key to decrypt. could be mutiple
|
||||||
func (o *OpenPGP) DecryptMessageVerifyPrivbinkeys(encryptedText string, veriferKey string, privateKeys []byte, passphrase string, verifyTime int64) (*DecryptSignedVerify, error) {
|
func (pm *PmCrypto) DecryptMessageVerifyPrivBinKeys(encryptedText string, verifierKey string, privateKeys []byte, passphrase string, verifyTime int64) (*models.DecryptSignedVerify, error) {
|
||||||
|
|
||||||
if len(veriferKey) > 0 {
|
if len(verifierKey) > 0 {
|
||||||
verifierRaw, err := UnArmor(veriferKey)
|
verifierRaw, err := armorUtils.Unarmor(verifierKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return o.decryptMessageVerifyAllBin(encryptedText, verifierRaw, privateKeys, passphrase, verifyTime)
|
return pm.decryptMessageVerifyAllBin(encryptedText, verifierRaw, privateKeys, passphrase, verifyTime)
|
||||||
}
|
}
|
||||||
return o.decryptMessageVerifyAllBin(encryptedText, nil, privateKeys, passphrase, verifyTime)
|
return pm.decryptMessageVerifyAllBin(encryptedText, nil, privateKeys, passphrase, verifyTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptMessageVerifyBinKeyPrivbinkeys decrypt message and verify the signature
|
// DecryptMessageVerifyBinKeyPrivBinKeys decrypt message and verify the signature
|
||||||
// veriferKey []byte: unarmored verifier keys
|
// verifierKey []byte: unarmored verifier keys
|
||||||
// privateKey []byte: unarmored private key to decrypt. could be mutiple
|
// privateKey []byte: unarmored private key to decrypt. could be mutiple
|
||||||
func (o *OpenPGP) DecryptMessageVerifyBinKeyPrivbinkeys(encryptedText string, veriferKey []byte, privateKeys []byte, passphrase string, verifyTime int64) (*DecryptSignedVerify, error) {
|
func (pm *PmCrypto) DecryptMessageVerifyBinKeyPrivBinKeys(encryptedText string, verifierKey []byte, privateKeys []byte, passphrase string, verifyTime int64) (*models.DecryptSignedVerify, error) {
|
||||||
return o.decryptMessageVerifyAllBin(encryptedText, veriferKey, privateKeys, passphrase, verifyTime)
|
return pm.decryptMessageVerifyAllBin(encryptedText, verifierKey, privateKeys, passphrase, verifyTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptMessageVerify decrypt message and verify the signature
|
// DecryptMessageVerify decrypt message and verify the signature
|
||||||
// veriferKey string: armored verifier keys
|
// verifierKey string: armored verifier keys
|
||||||
// privateKey string: private to decrypt
|
// privateKey string: private to decrypt
|
||||||
func (o *OpenPGP) DecryptMessageVerify(encryptedText string, veriferKey string, privateKey string, passphrase string, verifyTime int64) (*DecryptSignedVerify, error) {
|
func (pm *PmCrypto) DecryptMessageVerify(encryptedText string, verifierKey string, privateKey string, passphrase string, verifyTime int64) (*models.DecryptSignedVerify, error) {
|
||||||
if len(veriferKey) > 0 {
|
if len(verifierKey) > 0 {
|
||||||
verifierRaw, err := UnArmor(veriferKey)
|
verifierRaw, err := armorUtils.Unarmor(verifierKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return o.DecryptMessageVerifyBinKey(encryptedText, verifierRaw, privateKey, passphrase, verifyTime)
|
return pm.DecryptMessageVerifyBinKey(encryptedText, verifierRaw, privateKey, passphrase, verifyTime)
|
||||||
}
|
}
|
||||||
return o.DecryptMessageVerifyBinKey(encryptedText, nil, privateKey, passphrase, verifyTime)
|
return pm.DecryptMessageVerifyBinKey(encryptedText, nil, privateKey, passphrase, verifyTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptMessageVerifyBinKey decrypt message and verify the signature
|
// DecryptMessageVerifyBinKey decrypt message and verify the signature
|
||||||
// veriferKey []byte: unarmored verifier keys
|
// verifierKey []byte: unarmored verifier keys
|
||||||
// privateKey string: private to decrypt
|
// privateKey string: private to decrypt
|
||||||
func (o *OpenPGP) DecryptMessageVerifyBinKey(encryptedText string, veriferKey []byte, privateKey string, passphrase string, verifyTime int64) (*DecryptSignedVerify, error) {
|
func (pm *PmCrypto) DecryptMessageVerifyBinKey(encryptedText string, verifierKey []byte, privateKey string, passphrase string, verifyTime int64) (*models.DecryptSignedVerify, error) {
|
||||||
privateKeyRaw, err := UnArmor(privateKey)
|
privateKeyRaw, err := armorUtils.Unarmor(privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return o.decryptMessageVerifyAllBin(encryptedText, veriferKey, privateKeyRaw, passphrase, verifyTime)
|
return pm.decryptMessageVerifyAllBin(encryptedText, verifierKey, privateKeyRaw, passphrase, verifyTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decryptMessageVerifyAllBin
|
// decryptMessageVerifyAllBin
|
||||||
// decrypt_message_verify_single_key(private_key: string, passphras: string, encrypted : string, signature : string) : decrypt_sign_verify;
|
// decrypt_message_verify_single_key(private_key: string, passphras: string, encrypted : string, signature : string) : decrypt_sign_verify;
|
||||||
// decrypt_message_verify(passphras: string, encrypted : string, signature : string) : decrypt_sign_verify;
|
// decrypt_message_verify(passphras: string, encrypted : string, signature : string) : decrypt_sign_verify;
|
||||||
func (o *OpenPGP) decryptMessageVerifyAllBin(encryptedText string, veriferKey []byte, privateKey []byte, passphrase string, verifyTime int64) (*DecryptSignedVerify, error) {
|
func (pm *PmCrypto) decryptMessageVerifyAllBin(encryptedText string, verifierKey []byte, privateKey []byte, passphrase string, verifyTime int64) (*models.DecryptSignedVerify, error) {
|
||||||
privKey := bytes.NewReader(privateKey)
|
privKey := bytes.NewReader(privateKey)
|
||||||
privKeyEntries, err := openpgp.ReadKeyRing(privKey)
|
privKeyEntries, err := openpgp.ReadKeyRing(privKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -144,12 +147,12 @@ func (o *OpenPGP) decryptMessageVerifyAllBin(encryptedText string, veriferKey []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out := &DecryptSignedVerify{}
|
out := &models.DecryptSignedVerify{}
|
||||||
out.Verify = failed
|
out.Verify = failed
|
||||||
|
|
||||||
var verifierEntries openpgp.EntityList
|
var verifierEntries openpgp.EntityList
|
||||||
if len(veriferKey) > 0 {
|
if len(verifierKey) > 0 {
|
||||||
verifierReader := bytes.NewReader(veriferKey)
|
verifierReader := bytes.NewReader(verifierKey)
|
||||||
verifierEntries, err = openpgp.ReadKeyRing(verifierReader)
|
verifierEntries, err = openpgp.ReadKeyRing(verifierReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -162,7 +165,7 @@ func (o *OpenPGP) decryptMessageVerifyAllBin(encryptedText string, veriferKey []
|
||||||
out.Verify = noVerifier
|
out.Verify = noVerifier
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedio, err := unArmor(encryptedText)
|
encryptedio, err := internal.Unarmor(encryptedText)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -219,7 +222,7 @@ func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) {
|
||||||
if md.Signature.KeyLifetimeSecs != nil {
|
if md.Signature.KeyLifetimeSecs != nil {
|
||||||
expires = int64(*md.Signature.KeyLifetimeSecs) + created
|
expires = int64(*md.Signature.KeyLifetimeSecs) + created
|
||||||
}
|
}
|
||||||
if created - creationTimeOffset <= verifyTime && verifyTime <= expires {
|
if created-internal.CreationTimeOffset <= verifyTime && verifyTime <= expires {
|
||||||
md.SignatureError = nil
|
md.SignatureError = nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -234,12 +237,12 @@ func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) {
|
||||||
// plainText : the input
|
// plainText : the input
|
||||||
// privateKey : optional required when you want to sign
|
// privateKey : optional required when you want to sign
|
||||||
// passphrase : optional required when you pass the private key and this passphrase must could decrypt the private key
|
// passphrase : optional required when you pass the private key and this passphrase must could decrypt the private key
|
||||||
func (o *OpenPGP) EncryptMessage(plainText string, publicKey string, privateKey string, passphrase string, trim bool) (string, error) {
|
func (pm *PmCrypto) EncryptMessage(plainText string, publicKey string, privateKey string, passphrase string, trim bool) (string, error) {
|
||||||
rawPubKey, err := UnArmor(publicKey)
|
rawPubKey, err := armorUtils.Unarmor(publicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return o.EncryptMessageBinKey(plainText, rawPubKey, privateKey, passphrase, trim)
|
return pm.EncryptMessageBinKey(plainText, rawPubKey, privateKey, passphrase, trim)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptMessageBinKey encrypt message with unarmored public key, if pass private key and passphrase will also sign the message
|
// EncryptMessageBinKey encrypt message with unarmored public key, if pass private key and passphrase will also sign the message
|
||||||
|
|
@ -247,13 +250,13 @@ func (o *OpenPGP) EncryptMessage(plainText string, publicKey string, privateKey
|
||||||
// plainText : the input
|
// plainText : the input
|
||||||
// privateKey : optional required when you want to sign
|
// privateKey : optional required when you want to sign
|
||||||
// passphrase : optional required when you pass the private key and this passphrase must could decrypt the private key
|
// passphrase : optional required when you pass the private key and this passphrase must could decrypt the private key
|
||||||
func (o *OpenPGP) EncryptMessageBinKey(plainText string, publicKey []byte, privateKey string, passphrase string, trim bool) (string, error) {
|
func (pm *PmCrypto) EncryptMessageBinKey(plainText string, publicKey []byte, privateKey string, passphrase string, trim bool) (string, error) {
|
||||||
|
|
||||||
if trim {
|
if trim {
|
||||||
plainText = trimNewlines(plainText)
|
plainText = internal.TrimNewlines(plainText)
|
||||||
}
|
}
|
||||||
var outBuf bytes.Buffer
|
var outBuf bytes.Buffer
|
||||||
w, err := armor.Encode(&outBuf, pgpMessageType, armorHeader)
|
w, err := armor.Encode(&outBuf, armorUtils.MESSAGE_HEADER, internal.ArmorHeaders)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -287,11 +290,11 @@ func (o *OpenPGP) EncryptMessageBinKey(plainText string, publicKey []byte, priva
|
||||||
}
|
}
|
||||||
|
|
||||||
if signEntity == nil {
|
if signEntity == nil {
|
||||||
return "", errors.New("cannot sign message, singer key is not unlocked")
|
return "", errors.New("cannot sign message, signer key is not unlocked")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: o.getTimeGenerator() }
|
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pm.getTimeGenerator()}
|
||||||
|
|
||||||
ew, err := openpgp.Encrypt(w, pubKeyEntries, signEntity, nil, config)
|
ew, err := openpgp.Encrypt(w, pubKeyEntries, signEntity, nil, config)
|
||||||
|
|
||||||
|
|
@ -304,15 +307,15 @@ func (o *OpenPGP) EncryptMessageBinKey(plainText string, publicKey []byte, priva
|
||||||
//EncryptMessageWithPassword encrypt a plain text to pgp message with a password
|
//EncryptMessageWithPassword encrypt a plain text to pgp message with a password
|
||||||
//plainText string: clear text
|
//plainText string: clear text
|
||||||
//output string: armored pgp message
|
//output string: armored pgp message
|
||||||
func (o *OpenPGP) EncryptMessageWithPassword(plainText string, password string) (string, error) {
|
func (pm *PmCrypto) EncryptMessageWithPassword(plainText string, password string) (string, error) {
|
||||||
|
|
||||||
var outBuf bytes.Buffer
|
var outBuf bytes.Buffer
|
||||||
w, err := armor.Encode(&outBuf, pgpMessageType, armorHeader)
|
w, err := armor.Encode(&outBuf, armorUtils.MESSAGE_HEADER, internal.ArmorHeaders)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{ Time: o.getTimeGenerator() }
|
config := &packet.Config{Time: pm.getTimeGenerator()}
|
||||||
plaintext, err := openpgp.SymmetricallyEncrypt(w, []byte(password), nil, config)
|
plaintext, err := openpgp.SymmetricallyEncrypt(w, []byte(password), nil, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
@ -334,8 +337,8 @@ func (o *OpenPGP) EncryptMessageWithPassword(plainText string, password string)
|
||||||
//DecryptMessageWithPassword decrypt a pgp message with a password
|
//DecryptMessageWithPassword decrypt a pgp message with a password
|
||||||
//encrypted string : armored pgp message
|
//encrypted string : armored pgp message
|
||||||
//output string : clear text
|
//output string : clear text
|
||||||
func (o *OpenPGP) DecryptMessageWithPassword(encrypted string, password string) (string, error) {
|
func (pm *PmCrypto) DecryptMessageWithPassword(encrypted string, password string) (string, error) {
|
||||||
encryptedio, err := unArmor(encrypted)
|
encryptedio, err := internal.Unarmor(encrypted)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +347,7 @@ func (o *OpenPGP) DecryptMessageWithPassword(encrypted string, password string)
|
||||||
return []byte(password), nil
|
return []byte(password), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{ Time: o.getTimeGenerator() }
|
config := &packet.Config{Time: pm.getTimeGenerator()}
|
||||||
md, err := openpgp.ReadMessage(encryptedio.Body, nil, prompt, config)
|
md, err := openpgp.ReadMessage(encryptedio.Body, nil, prompt, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
83
crypto/mime.go
Normal file
83
crypto/mime.go
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"proton/pmmime"
|
||||||
|
"net/mail"
|
||||||
|
"strings"
|
||||||
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
|
"net/textproto"
|
||||||
|
"io/ioutil"
|
||||||
|
"bytes"
|
||||||
|
"golang.org/x/crypto/openpgp"
|
||||||
|
"proton/pmcrypto/armor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ======================== Attachments Collector ==============
|
||||||
|
// Collect contents of all attachment parts and return
|
||||||
|
// them as a string
|
||||||
|
|
||||||
|
|
||||||
|
func (pm PmCrypto) parseMIME(mimeBody string, verifierKey []byte) (*pmmime.BodyCollector, int, []string, []string, error) {
|
||||||
|
pubKey := bytes.NewReader(verifierKey)
|
||||||
|
pubKeyEntries, err := openpgp.ReadKeyRing(pubKey)
|
||||||
|
|
||||||
|
mm, err := mail.ReadMessage(strings.NewReader(mimeBody))
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, nil, nil, err
|
||||||
|
}
|
||||||
|
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pm.getTimeGenerator()}
|
||||||
|
|
||||||
|
h := textproto.MIMEHeader(mm.Header)
|
||||||
|
mmBodyData, err := ioutil.ReadAll(mm.Body)
|
||||||
|
|
||||||
|
printAccepter := pmmime.NewMIMEPrinter()
|
||||||
|
bodyCollector := pmmime.NewBodyCollector(printAccepter)
|
||||||
|
attachmentsCollector := pmmime.NewAttachmentsCollector(bodyCollector)
|
||||||
|
mimeVisitor := pmmime.NewMimeVisitor(attachmentsCollector)
|
||||||
|
str, err := armor.ArmorKey(verifierKey)
|
||||||
|
signatureCollector := newSignatureCollector(mimeVisitor, pubKeyEntries, config)
|
||||||
|
err = pmmime.VisitAll(bytes.NewReader(mmBodyData), h, signatureCollector)
|
||||||
|
|
||||||
|
verified := signatureCollector.verified
|
||||||
|
body := bodyCollector
|
||||||
|
atts := attachmentsCollector.GetAttachments()
|
||||||
|
attHeaders := attachmentsCollector.GetAttHeaders()
|
||||||
|
|
||||||
|
return body, verified, atts, attHeaders, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// define call back interface
|
||||||
|
type MIMECallbacks interface {
|
||||||
|
OnBody(body string, mimetype string)
|
||||||
|
OnAttachment(headers string, data []byte)
|
||||||
|
// Encrypted headers can be an attachment and thus be placed at the end of the mime structure
|
||||||
|
OnEncryptedHeaders(headers string)
|
||||||
|
OnVerified(verified int)
|
||||||
|
OnError(err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *PmCrypto) DecryptMIMEMessage(encryptedText string, verifierKey []byte, privateKeys []byte,
|
||||||
|
passphrase string, callbacks MIMECallbacks, verifyTime int64) {
|
||||||
|
decsignverify, err := pm.decryptMessageVerifyAllBin(encryptedText, verifierKey, privateKeys, passphrase, verifyTime)
|
||||||
|
if err != nil {
|
||||||
|
callbacks.OnError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
body, verified, attachments, attachmentHeaders, err := pm.parseMIME(decsignverify.Plaintext, verifierKey)
|
||||||
|
if err != nil {
|
||||||
|
callbacks.OnError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bodyContent, bodyMimeType := body.GetBody()
|
||||||
|
callbacks.OnBody(bodyContent, bodyMimeType)
|
||||||
|
for i := 0; i < len(attachments); i++ {
|
||||||
|
callbacks.OnAttachment(attachmentHeaders[i], []byte(attachments[i]))
|
||||||
|
}
|
||||||
|
callbacks.OnEncryptedHeaders("")
|
||||||
|
if decsignverify.Verify == notSigned {
|
||||||
|
callbacks.OnVerified(verified)
|
||||||
|
} else {
|
||||||
|
callbacks.OnVerified(decsignverify.Verify)
|
||||||
|
}
|
||||||
|
}
|
||||||
411
crypto/mime_test.go
Normal file
411
crypto/mime_test.go
Normal file
|
|
@ -0,0 +1,411 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"proton/pmcrypto/internal"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const publicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
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
|
||||||
|
OQTmvM6R
|
||||||
|
=DvFv
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----`
|
||||||
|
const testMessage = `-----BEGIN PGP MESSAGE-----
|
||||||
|
Version: ProtonMail
|
||||||
|
Comment: https://protonmail.com
|
||||||
|
|
||||||
|
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
|
||||||
|
LloBMV1YNGsW45M+oQ==
|
||||||
|
=BRHT
|
||||||
|
-----END PGP MESSAGE-----`
|
||||||
|
const privatekeypassword = "test"
|
||||||
|
const privatekey = `
|
||||||
|
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
Version: PmCrypto.js v3.1.2
|
||||||
|
Comment: https://openpgpjs.org
|
||||||
|
|
||||||
|
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
|
||||||
|
=xWqS
|
||||||
|
-----END PGP PRIVATE KEY BLOCK-----
|
||||||
|
`
|
||||||
|
|
||||||
|
// define call back interface
|
||||||
|
type Callbacks struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Callbacks) OnBody(body string, mimetype string) {
|
||||||
|
fmt.Println(body)
|
||||||
|
}
|
||||||
|
func (t Callbacks) OnAttachment(headers string, data []byte) {
|
||||||
|
fmt.Println(headers)
|
||||||
|
}
|
||||||
|
func (t Callbacks) OnEncryptedHeaders(headers string) {
|
||||||
|
fmt.Println(headers)
|
||||||
|
}
|
||||||
|
func (t Callbacks) OnVerified(verified int) {
|
||||||
|
fmt.Println(verified)
|
||||||
|
}
|
||||||
|
func (t Callbacks) OnError(err error) {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecrypt(t *testing.T) {
|
||||||
|
callbacks := Callbacks{}
|
||||||
|
o := PmCrypto{}
|
||||||
|
block, _ := internal.Unarmor(publicKey)
|
||||||
|
publicKeyUnarmored, _ := ioutil.ReadAll(block.Body)
|
||||||
|
block, _ = internal.Unarmor(privatekey)
|
||||||
|
privateKeyUnarmored, _ := ioutil.ReadAll(block.Body)
|
||||||
|
o.DecryptMIMEMessage(testMessage, publicKeyUnarmored, privateKeyUnarmored, privatekeypassword,
|
||||||
|
&callbacks, o.GetTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
testMessage :=
|
||||||
|
`Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg=pgp-sha256; boundary="---------------------4a9ea9f4dad3f36079bdb3f1e7b75bd0"; charset=UTF-8
|
||||||
|
X-Spam-Status: No, score=1.2 required=7.0 tests=ALL_TRUSTED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, FREEMAIL_REPLYTO_END_DIGIT,HTML_IMAGE_ONLY_08,HTML_MESSAGE autolearn=no autolearn_force=no version=3.4.0
|
||||||
|
X-Spam-Level: *
|
||||||
|
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.protonmail.ch
|
||||||
|
|
||||||
|
-----------------------4a9ea9f4dad3f36079bdb3f1e7b75bd0
|
||||||
|
Content-Type: multipart/mixed; boundary="---------------------f0e64db835d0f5c3674df52a164b06bb"
|
||||||
|
|
||||||
|
-----------------------f0e64db835d0f5c3674df52a164b06bb
|
||||||
|
Content-Type: multipart/alternative; boundary="---------------------3ca028eaeffb3ca0fb0dd6461f639c2b"
|
||||||
|
|
||||||
|
-----------------------3ca028eaeffb3ca0fb0dd6461f639c2b
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
Content-Type: text/plain;charset=utf-8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Screenshot from 2018-02-06 17-13-21.png]
|
||||||
|
|
||||||
|
--=C2=A0
|
||||||
|
Julien Palard
|
||||||
|
https://mdk.fr
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------3ca028eaeffb3ca0fb0dd6461f639c2b
|
||||||
|
Content-Type: multipart/related; boundary="---------------------ce717c368c2d3981c954ad7c46cd7bf2"
|
||||||
|
|
||||||
|
-----------------------ce717c368c2d3981c954ad7c46cd7bf2
|
||||||
|
Content-Type: text/html;charset=utf-8
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
|
||||||
|
PGRpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2IGNsYXNzPSJwcm90b25tYWls
|
||||||
|
X3NpZ25hdHVyZV9ibG9jayI+PGRpdiBjbGFzcz0icHJvdG9ubWFpbF9zaWduYXR1cmVfYmxvY2st
|
||||||
|
dXNlciI+PGRpdj48aW1nIHNyYz0iY2lkOjQ2MDk4ZTliQHByb3Rvbm1haWwuY29tIiBjbGFzcz0i
|
||||||
|
cHJvdG9uLWVtYmVkZGVkIiBhbHQ9IlNjcmVlbnNob3QgZnJvbSAyMDE4LTAyLTA2IDE3LTEzLTIx
|
||||||
|
LnBuZyI+PGJyPjwvZGl2PjxkaXY+LS0mbmJzcDs8YnI+PC9kaXY+PGRpdj5KdWxpZW4gUGFsYXJk
|
||||||
|
PGJyPjwvZGl2PjxkaXY+PGNvZGUgc3R5bGU9ImZvbnQtZmFtaWx5OidTRk1vbm8tUmVndWxhcics
|
||||||
|
IENvbnNvbGFzLCAnTGliZXJhdGlvbiBNb25vJywgTWVubG8sIENvdXJpZXIsIG1vbm9zcGFjZTtm
|
||||||
|
b250LXNpemU6MTEuODk5OTk5NjE4NTMwMjczcHg7cGFkZGluZzowcHg7bWFyZ2luOjBweDtiYWNr
|
||||||
|
Z3JvdW5kLWNvbG9yOnRyYW5zcGFyZW50O3doaXRlLXNwYWNlOnByZTtib3JkZXI6MHB4O2Rpc3Bs
|
||||||
|
YXk6aW5saW5lO292ZXJmbG93OnZpc2libGU7bGluZS1oZWlnaHQ6aW5oZXJpdDsiPjxhIGhyZWY9
|
||||||
|
Imh0dHBzOi8vbWRrLmZyIj5odHRwczovL21kay5mcjwvYT48L2NvZGU+PGJyPjwvZGl2PjwvZGl2
|
||||||
|
PjxkaXYgY2xhc3M9InByb3Rvbm1haWxfc2lnbmF0dXJlX2Jsb2NrLXByb3RvbiBwcm90b25tYWls
|
||||||
|
X3NpZ25hdHVyZV9ibG9jay1lbXB0eSI+PGJyPjwvZGl2PjwvZGl2PjwvZGl2Pg==
|
||||||
|
-----------------------ce717c368c2d3981c954ad7c46cd7bf2--
|
||||||
|
-----------------------3ca028eaeffb3ca0fb0dd6461f639c2b--
|
||||||
|
-----------------------f0e64db835d0f5c3674df52a164b06bb
|
||||||
|
Content-Type: image/png; filename="Screenshot from 2018-02-06 17-13-21.png"; name="Screenshot from 2018-02-06 17-13-21.png"
|
||||||
|
Content-Disposition: inline; filename="Screenshot from 2018-02-06 17-13-21.png"; name="Screenshot from 2018-02-06 17-13-21.png"
|
||||||
|
Content-ID: <46098e9b@protonmail.com>
|
||||||
|
|
||||||
|
wsBcBAEBCAAQBQJbjodcCRDdVS3pfakUGgAAlhoH/2jBRjOSx5EdkiyyNcCT
|
||||||
|
4DVm+ACoF1KTWE5fLRuDPvSiD934cFoZShJs32r0Wcj/4W4tVhLYzjjtf6xO
|
||||||
|
Ymqe0p3o4oYxxMXIAd4COrnOPGjeD1ausqT6iUCAadqXoDYfowEg4f0Wd0RK
|
||||||
|
ElsP/OZaDjsNoRE3WeRcHTr5XWZxhEsIMgnW591iaTliYvbysLoQ08i3G53c
|
||||||
|
p6q+IANRznx5rDhMdo+shFvhcI2Zszg6X2WuCMhFtUyrqEN8WlZYXMX8PGPO
|
||||||
|
1kNDRl7B7/r4Ap+FffLpeYw+8rG6lQXGc3RCOAnfMq9X/9Ziqzxr7flYtRJH
|
||||||
|
RIzX2CG47PuGl/uvImFW/Iw=
|
||||||
|
|
||||||
|
-----------------------f0e64db835d0f5c3674df52a164b06bb
|
||||||
|
Content-Type: application/pgp-keys; filename="publickey - kaykeytest3@protonmail.com - 0xE1DADAE3.asc"; name="publickey - kaykeytest3@protonmail.com - 0xE1DADAE3.asc"
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
Content-Disposition: attachment; filename="publickey - kaykeytest3@protonmail.com - 0xE1DADAE3.asc"; name="publickey - kaykeytest3@protonmail.com - 0xE1DADAE3.asc"
|
||||||
|
|
||||||
|
LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tDQpWZXJzaW9uOiBPcGVuUEdQLmpz
|
||||||
|
IHYzLjEuMg0KQ29tbWVudDogaHR0cHM6Ly9vcGVucGdwanMub3JnDQoNCnhzQk5CRnQ2N2I4QkNB
|
||||||
|
QzBTMlU3VUJ3dnkyUnZqcEpwOHlyMlE0R25oNzk0QjUwVG1TMlViTXJRaEovaQpUWFRTZmJhb21l
|
||||||
|
NkdkcmJhSjlvVW0xY2hhMU5hVlNnWHE0RVB2WWxmSWVVdkt1U0tnTVdxaVMzT2xSdGYKT3JwMVZp
|
||||||
|
dXNpZWtldVczL2JtYUZBbzFLQWZvajBMNlF6cVVIY3ZZNnY1RExoWGV2MWlaUW9TN2lrQk9PCmor
|
||||||
|
Z05lUDJabjVIOXdQTFlxdWlqK0pnWFY4djRRQk5uNU82NUNYRkZIbjl1Mzl1Yng2bDJtY2tqaDVm
|
||||||
|
VQppU1FiUkh2RzhIdG96Y2xIcWV1bjBpanNjZEtoOTBsaENsWHlDcHlkZ2JwT2pjL2dDQ2R3WmVh
|
||||||
|
djNNSG0KZnhsd2VReDhmc0xxZ1h5TlNFd3pyODh0MTFWMFQ4TmRjeFdia1lRNllQN2R4UU10RkU0
|
||||||
|
bWM5akxBQkVCCkFBSE5PU0pyWVhsclpYbDBaWE4wTTBCd2NtOTBiMjV0WVdsc0xtTnZiU0lnUEd0
|
||||||
|
aGVXdGxlWFJsYzNRegpRSEJ5YjNSdmJtMWhhV3d1WTI5dFBzTEFkUVFRQVFnQUtRVUNXM3J0dndZ
|
||||||
|
TENRY0lBd0lKRU4xVkxlbDkKcVJRYUJCVUlDZ0lERmdJQkFoa0JBaHNEQWg0QkFBQ0dEZ2Y5SHVq
|
||||||
|
aG9QUGN5SHpLd25JbFJJaENRL1dLCm13SVVFdEw4eU03aGRvci9zK0kyL1A3WkJHWE1ReXBKb3JD
|
||||||
|
YTU1NUY2ODRMZnpWdUtBUVFMdXZpNHR6aQo5N2JSNE1ldHY4a2ptSUI1Rk0vNUhpWllWd090SDFK
|
||||||
|
dU5iM2RQWG9CVjJha09ScnFCeVRjbjEyeUIwOVkKd0tZR0Y4K25XNFhLU1F2V3VBWWVIZ0dQKzMz
|
||||||
|
ZTdCc0VvODhuRmJJUXl2cmUzUTN0TkJrWTVVVnA2L1M2ClpLZWJwaEFRQVlzM0ZVVlZVeThlZkhr
|
||||||
|
aEFmZFlSdUFBUUFoWnJGanU0V1J0RGZkUHdLR0UzZDZsUGswSApNSFNTUXNHb2thQTVoTnUycE1S
|
||||||
|
Mnl5UmtUa3JyNnRXbmlET2ZvSmtKcmc2VllHNVRwaHZnOE43dVdzZHQKZkhDdDBwWW9uYTRzclZx
|
||||||
|
a0RzN0FUUVJiZXUyL0FRZ0F6b2tCSGZucnFXUXE4RUVSYUVlOUpmZkQ3V0FpCnZyU29lNDdxQ05l
|
||||||
|
S2I2MmcvLzh0Q1dKMHVlRExTMFRyY0V4cnVzUi8rSFdoYUFTV2srL0lPTGhjRTcrVgp4V2Nab0dp
|
||||||
|
bzNuc1puTktWdnFhendNSW1vMnFqdUllUnVCVkJqRW5OOERhOXlxNkJ3YVkvSEs2czM5Y3IKQVVV
|
||||||
|
d2FtWjVuMDNtSFR6MzBMQllYR1VldVc5c3Z4NDIzbTlXb3N2WlQvUWRKWW1qMG44NmpGNGs2Tnh2
|
||||||
|
ClV4ejR1bmV1YWt1Wld5NmNURHg1WFdWVWF1YzlyV1Z5Uzk3cjJ0NllpRlF6MTFiOU5oZm4rcDVs
|
||||||
|
UmdZbgpzMzQwT1MyVmppK1BVeUVKZ2YzYi9MQlJ5V3Erbk1Vc2lRV09yYlQxblVCVzNRdDViWWhH
|
||||||
|
MUhnT1o5eEoKVjd2dndSZHFwQ1p2cVFBUkFRQUJ3c0JmQkJnQkNBQVRCUUpiZXUyL0NSRGRWUzNw
|
||||||
|
ZmFrVUdnSWJEQUFBClhrTUgvaTBoTnRwRWIrYUZONC9Ba0JCam1GOFJZV243anRyK2UyU05STHdF
|
||||||
|
RUMxcmdmakhjWXZnanJFTQo2Y3hBcXVzSWJKSEdnSUVYZ0s1YUlNOHBGLzRuamN2VXVxa0x1b1o3
|
||||||
|
QVJsanpwUTcvaHhyc0FNWnFYR2gKeEU4eXJZVlY0dGhhZWw0Q1NRUTRvRWlpbXB4Z28velE5bzhk
|
||||||
|
NGNQUTM4Ni9VNEgvMm9OczFUMElCOTZWCkJsTy9pM0w5eGM4K2w4RG8vcm5ieVV1Ym9LUVNKZmtp
|
||||||
|
RXNLMkRabEZoOVArdVltQ1AzVGJSb2NIUFZtVwpBT3NHVVhJSXROaVNTc05ORUlHeVBSNE8rMXRq
|
||||||
|
VUJPMFNHRnZoVVZUNnJLYTlaYUVyMzI2ZmU2S0pmZU8KYTl4a21WZEdaQm9SdENmbHhiakdnYjRq
|
||||||
|
dTJ3Z1E1TE5KWUNWZy9WRkxIRGI3MjQ9DQo9YmNvMw0KLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkg
|
||||||
|
QkxPQ0stLS0tLQ0KDQo=
|
||||||
|
-----------------------f0e64db835d0f5c3674df52a164b06bb--
|
||||||
|
-----------------------4a9ea9f4dad3f36079bdb3f1e7b75bd0
|
||||||
|
Content-Type: application/pgp-signature; name="signature.asc"
|
||||||
|
Content-Description: PmCrypto digital signature
|
||||||
|
Content-Disposition: attachment; filename="signature.asc"
|
||||||
|
|
||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
Version: ProtonMail
|
||||||
|
Comment: https://protonmail.com
|
||||||
|
|
||||||
|
wsBcBAEBCAAQBQJbjodcCRDdVS3pfakUGgAAlhoH/2jBRjOSx5EdkiyyNcCT
|
||||||
|
4DVm+ACoF1KTWE5fLRuDPvSiD934cFoZShJs32r0Wcj/4W4tVhLYzjjtf6xO
|
||||||
|
Ymqe0p3o4oYxxMXIAd4COrnOPGjeD1ausqT6iUCAadqXoDYfowEg4f0Wd0RK
|
||||||
|
ElsP/OZaDjsNoRE3WeRcHTr5XWZxhEsIMgnW591iaTliYvbysLoQ08i3G53c
|
||||||
|
p6q+IANRznx5rDhMdo+shFvhcI2Zszg6X2WuCMhFtUyrqEN8WlZYXMX8PGPO
|
||||||
|
1kNDRl7B7/r4Ap+FffLpeYw+8rG6lQXGc3RCOAnfMq9X/9Ziqzxr7flYtRJH
|
||||||
|
RIzX2CG47PuGl/uvImFW/Iw=
|
||||||
|
=t7ak
|
||||||
|
-----END PGP SIGNATURE-----
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------4a9ea9f4dad3f36079bdb3f1e7b75bd0--
|
||||||
|
`
|
||||||
|
o := PmCrypto{}
|
||||||
|
body, _, atts, attHeaders, err := o.parseMIME(testMessage, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("==BODY:")
|
||||||
|
fmt.Println(body.GetBody())
|
||||||
|
fmt.Println("==BODY HEADERS:")
|
||||||
|
fmt.Println(body.GetHeaders())
|
||||||
|
|
||||||
|
fmt.Println("==ATTACHMENTS:")
|
||||||
|
fmt.Println(len(atts))
|
||||||
|
for i, attachment := range atts {
|
||||||
|
fmt.Println("==ATTACHMENT HEADERS:")
|
||||||
|
fmt.Println(attHeaders[i])
|
||||||
|
fmt.Println("==ATTACHMENT:")
|
||||||
|
fmt.Println(attachment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package pm
|
package crypto
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
// OpenPGP structure to manage mutiple address keys and user keys
|
// PmCrypto structure to manage multiple address keys and user keys
|
||||||
type OpenPGP struct {
|
// Called PGP crypto because it cannot have the same name as the package by gomobile's ridiculous rules.
|
||||||
addresses []*Address
|
type PmCrypto struct {
|
||||||
|
|
||||||
//latestServerTime unix time cache
|
//latestServerTime unix time cache
|
||||||
latestServerTime int64
|
latestServerTime int64
|
||||||
latestClientTime time.Time
|
latestClientTime time.Time
|
||||||
|
|
@ -13,28 +12,28 @@ type OpenPGP struct {
|
||||||
|
|
||||||
// //AddAddress add a new address to key ring
|
// //AddAddress add a new address to key ring
|
||||||
// //add a new address into addresses list
|
// //add a new address into addresses list
|
||||||
// func (pgp *OpenPGP) AddAddress(address *Address) (bool, error) {
|
// func (pgp *PmCrypto) AddAddress(address *Address) (bool, error) {
|
||||||
// return true, errors.New("this is not implemented yet, will add this later")
|
// return true, errors.New("this is not implemented yet, will add this later")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// //RemoveAddress remove address from the keyring
|
// //RemoveAddress remove address from the keyring
|
||||||
// //
|
// //
|
||||||
// //#remove a exsit address from the list based on address id
|
// //#remove a exsit address from the list based on address id
|
||||||
// func (pgp *OpenPGP) RemoveAddress(addressID string) (bool, error) {
|
// func (pgp *PmCrypto) RemoveAddress(addressID string) (bool, error) {
|
||||||
// return true, errors.New("this is not implemented yet, will add this later")
|
// return true, errors.New("this is not implemented yet, will add this later")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// //CleanAddresses clear all addresses in keyring
|
// //CleanAddresses clear all addresses in keyring
|
||||||
// func (pgp *OpenPGP) CleanAddresses() (bool, error) {
|
// func (pgp *PmCrypto) CleanAddresses() (bool, error) {
|
||||||
// return true, errors.New("this is not implemented yet, will add this later")
|
// return true, errors.New("this is not implemented yet, will add this later")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// //EncryptMessage encrypt message use address id
|
// //EncryptMessage encrypt message use address id
|
||||||
// func (pgp *OpenPGP) EncryptMessage(addressID string, plainText string, passphrase string, trim bool) (string, error) {
|
// func (pgp *PmCrypto) EncryptMessage(addressID string, plainText string, passphrase string, trim bool) (string, error) {
|
||||||
// return "", errors.New("this is not implemented yet, will add this later")
|
// return "", errors.New("this is not implemented yet, will add this later")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// //DecryptMessage decrypt message, this will lookup all keys
|
// //DecryptMessage decrypt message, this will lookup all keys
|
||||||
// func (pgp *OpenPGP) DecryptMessage(encryptText string, passphras string) (string, error) {
|
// func (pgp *PmCrypto) DecryptMessage(encryptText string, passphras string) (string, error) {
|
||||||
// return "", errors.New("this is not implemented yet, will add this later")
|
// return "", errors.New("this is not implemented yet, will add this later")
|
||||||
// }
|
// }
|
||||||
|
|
@ -1,19 +1,20 @@
|
||||||
package pm
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
|
"proton/pmcrypto/armor"
|
||||||
|
"proton/pmcrypto/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
//RandomToken ...
|
//RandomToken ...
|
||||||
func RandomToken() ([]byte, error) {
|
func (pm *PmCrypto) RandomToken() ([]byte, error) {
|
||||||
config := &packet.Config{DefaultCipher: packet.CipherAES256}
|
config := &packet.Config{DefaultCipher: packet.CipherAES256}
|
||||||
keySize := config.DefaultCipher.KeySize()
|
keySize := config.DefaultCipher.KeySize()
|
||||||
symKey := make([]byte, keySize)
|
symKey := make([]byte, keySize)
|
||||||
|
|
@ -24,7 +25,7 @@ func RandomToken() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomTokenWith ...
|
// RandomTokenWith ...
|
||||||
func RandomTokenWith(size int) ([]byte, error) {
|
func (pm *PmCrypto) RandomTokenWith(size int) ([]byte, error) {
|
||||||
config := &packet.Config{DefaultCipher: packet.CipherAES256}
|
config := &packet.Config{DefaultCipher: packet.CipherAES256}
|
||||||
symKey := make([]byte, size)
|
symKey := make([]byte, size)
|
||||||
if _, err := io.ReadFull(config.Random(), symKey); err != nil {
|
if _, err := io.ReadFull(config.Random(), symKey); err != nil {
|
||||||
|
|
@ -34,7 +35,7 @@ func RandomTokenWith(size int) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetSessionFromKeyPacketBinkeys get session key no encoding in and out
|
//GetSessionFromKeyPacketBinkeys get session key no encoding in and out
|
||||||
func GetSessionFromKeyPacketBinkeys(keyPackage []byte, privateKey []byte, passphrase string) (*SessionSplit, error) {
|
func (pm *PmCrypto) GetSessionFromKeyPacketBinkeys(keyPackage []byte, privateKey []byte, passphrase string) (*models.SessionSplit, error) {
|
||||||
|
|
||||||
keyReader := bytes.NewReader(keyPackage)
|
keyReader := bytes.NewReader(keyPackage)
|
||||||
packets := packet.NewReader(keyReader)
|
packets := packet.NewReader(keyReader)
|
||||||
|
|
@ -75,7 +76,7 @@ func GetSessionFromKeyPacketBinkeys(keyPackage []byte, privateKey []byte, passph
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetSessionFromKeyPacket get session key no encoding in and out
|
//GetSessionFromKeyPacket get session key no encoding in and out
|
||||||
func GetSessionFromKeyPacket(keyPackage []byte, privateKey string, passphrase string) (*SessionSplit, error) {
|
func (pm *PmCrypto) GetSessionFromKeyPacket(keyPackage []byte, privateKey string, passphrase string) (*models.SessionSplit, error) {
|
||||||
|
|
||||||
keyReader := bytes.NewReader(keyPackage)
|
keyReader := bytes.NewReader(keyPackage)
|
||||||
packets := packet.NewReader(keyReader)
|
packets := packet.NewReader(keyReader)
|
||||||
|
|
@ -116,16 +117,16 @@ func GetSessionFromKeyPacket(keyPackage []byte, privateKey string, passphrase st
|
||||||
}
|
}
|
||||||
|
|
||||||
//KeyPacketWithPublicKey ...
|
//KeyPacketWithPublicKey ...
|
||||||
func KeyPacketWithPublicKey(sessionSplit *SessionSplit, publicKey string) ([]byte, error) {
|
func (pm *PmCrypto) KeyPacketWithPublicKey(sessionSplit *models.SessionSplit, publicKey string) ([]byte, error) {
|
||||||
pubkeyRaw, err := UnArmor(publicKey)
|
pubkeyRaw, err := armor.Unarmor(publicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return KeyPacketWithPublicKeyBin(sessionSplit, pubkeyRaw)
|
return pm.KeyPacketWithPublicKeyBin(sessionSplit, pubkeyRaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyPacketWithPublicKeyBin ...
|
// KeyPacketWithPublicKeyBin ...
|
||||||
func KeyPacketWithPublicKeyBin(sessionSplit *SessionSplit, publicKey []byte) ([]byte, error) {
|
func (pm *PmCrypto) KeyPacketWithPublicKeyBin(sessionSplit *models.SessionSplit, publicKey []byte) ([]byte, error) {
|
||||||
publicKeyReader := bytes.NewReader(publicKey)
|
publicKeyReader := bytes.NewReader(publicKey)
|
||||||
pubKeyEntries, err := openpgp.ReadKeyRing(publicKeyReader)
|
pubKeyEntries, err := openpgp.ReadKeyRing(publicKeyReader)
|
||||||
|
|
||||||
|
|
@ -170,7 +171,7 @@ func KeyPacketWithPublicKeyBin(sessionSplit *SessionSplit, publicKey []byte) ([]
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetSessionFromSymmetricPacket ...
|
//GetSessionFromSymmetricPacket ...
|
||||||
func GetSessionFromSymmetricPacket(keyPackage []byte, password string) (*SessionSplit, error) {
|
func (pm *PmCrypto) GetSessionFromSymmetricPacket(keyPackage []byte, password string) (*models.SessionSplit, error) {
|
||||||
|
|
||||||
keyReader := bytes.NewReader(keyPackage)
|
keyReader := bytes.NewReader(keyPackage)
|
||||||
packets := packet.NewReader(keyReader)
|
packets := packet.NewReader(keyReader)
|
||||||
|
|
@ -196,7 +197,7 @@ func GetSessionFromSymmetricPacket(keyPackage []byte, password string) (*Session
|
||||||
for _, s := range symKeys {
|
for _, s := range symKeys {
|
||||||
key, cipherFunc, err := s.Decrypt(pwdRaw)
|
key, cipherFunc, err := s.Decrypt(pwdRaw)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return &SessionSplit{
|
return &models.SessionSplit{
|
||||||
Session: key,
|
Session: key,
|
||||||
Algo: getAlgo(cipherFunc),
|
Algo: getAlgo(cipherFunc),
|
||||||
}, nil
|
}, nil
|
||||||
|
|
@ -209,7 +210,7 @@ func GetSessionFromSymmetricPacket(keyPackage []byte, password string) (*Session
|
||||||
}
|
}
|
||||||
|
|
||||||
// SymmetricKeyPacketWithPassword ...
|
// SymmetricKeyPacketWithPassword ...
|
||||||
func SymmetricKeyPacketWithPassword(sessionSplit *SessionSplit, password string) ([]byte, error) {
|
func (pm *PmCrypto) SymmetricKeyPacketWithPassword(sessionSplit *models.SessionSplit, password string) ([]byte, error) {
|
||||||
outbuf := &bytes.Buffer{}
|
outbuf := &bytes.Buffer{}
|
||||||
|
|
||||||
cf := cipherFunc(sessionSplit.Algo)
|
cf := cipherFunc(sessionSplit.Algo)
|
||||||
|
|
@ -249,7 +250,7 @@ func cipherFunc(algo string) packet.CipherFunction {
|
||||||
return packet.CipherAES256
|
return packet.CipherAES256
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSessionSplit(ek *packet.EncryptedKey) (*SessionSplit, error) {
|
func getSessionSplit(ek *packet.EncryptedKey) (*models.SessionSplit, error) {
|
||||||
if ek == nil {
|
if ek == nil {
|
||||||
return nil, errors.New("can't decrypt key packet")
|
return nil, errors.New("can't decrypt key packet")
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +266,7 @@ func getSessionSplit(ek *packet.EncryptedKey) (*SessionSplit, error) {
|
||||||
return nil, errors.New("can't decrypt key packet key is nil")
|
return nil, errors.New("can't decrypt key packet key is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &SessionSplit{
|
return &models.SessionSplit{
|
||||||
Session: ek.Key,
|
Session: ek.Key,
|
||||||
Algo: algo,
|
Algo: algo,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
@ -282,81 +283,3 @@ func getAlgo(cipher packet.CipherFunction) string {
|
||||||
|
|
||||||
return algo
|
return algo
|
||||||
}
|
}
|
||||||
|
|
||||||
//encode length based on 4.2.2. in the RFC
|
|
||||||
func encodedLength(length int) (b []byte) {
|
|
||||||
if length < 192 {
|
|
||||||
b = append(b, byte(length))
|
|
||||||
} else if length < 8384 {
|
|
||||||
length = length - 192
|
|
||||||
b = append(b, 192+byte(length>>8))
|
|
||||||
b = append(b, byte(length))
|
|
||||||
} else {
|
|
||||||
b = append(b, byte(255))
|
|
||||||
b = append(b, byte(length>>24))
|
|
||||||
b = append(b, byte(length>>16))
|
|
||||||
b = append(b, byte(length>>8))
|
|
||||||
b = append(b, byte(length))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//SeparateKeyAndData ...
|
|
||||||
func SeparateKeyAndData(encrypted string) (*EncryptedSplit, error) {
|
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
encryptedRaw, err := UnArmor(encrypted)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
encryptedReader := bytes.NewReader(encryptedRaw)
|
|
||||||
|
|
||||||
//kr *KeyRing, r io.Reader) (key *SymmetricKey, symEncryptedData []byte,
|
|
||||||
packets := packet.NewReader(encryptedReader)
|
|
||||||
|
|
||||||
outSplit := &EncryptedSplit{}
|
|
||||||
|
|
||||||
// Save encrypted key and signature apart
|
|
||||||
var ek *packet.EncryptedKey
|
|
||||||
// var decryptErr error
|
|
||||||
for {
|
|
||||||
var p packet.Packet
|
|
||||||
if p, err = packets.Next(); err == io.EOF {
|
|
||||||
err = nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
switch p := p.(type) {
|
|
||||||
case *packet.EncryptedKey:
|
|
||||||
// We got an encrypted key. Try to decrypt it with each available key
|
|
||||||
if ek != nil && ek.Key != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ek = p
|
|
||||||
break
|
|
||||||
case *packet.SymmetricallyEncrypted:
|
|
||||||
var packetContents []byte
|
|
||||||
if packetContents, err = ioutil.ReadAll(p.Contents); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
encodedLength := encodedLength(len(packetContents) + 1)
|
|
||||||
var symEncryptedData []byte
|
|
||||||
symEncryptedData = append(symEncryptedData, byte(210))
|
|
||||||
symEncryptedData = append(symEncryptedData, encodedLength...)
|
|
||||||
symEncryptedData = append(symEncryptedData, byte(1))
|
|
||||||
symEncryptedData = append(symEncryptedData, packetContents...)
|
|
||||||
|
|
||||||
outSplit.DataPacket = symEncryptedData
|
|
||||||
break
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
ek.Serialize(&buf)
|
|
||||||
outSplit.KeyPacket = buf.Bytes()
|
|
||||||
|
|
||||||
return outSplit, err
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package pm
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -7,28 +7,19 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
"golang.org/x/crypto/openpgp/clearsign"
|
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
errors2 "golang.org/x/crypto/openpgp/errors"
|
errors2 "golang.org/x/crypto/openpgp/errors"
|
||||||
"io"
|
"io"
|
||||||
|
"proton/pmcrypto/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//ReadClearSignedMessage read clear message from a clearsign package
|
|
||||||
func ReadClearSignedMessage(signedMessage string) (string, error) {
|
|
||||||
modulusBlock, rest := clearsign.Decode([]byte(signedMessage))
|
|
||||||
if len(rest) != 0 {
|
|
||||||
return "", errors.New("pmapi: extra data after modulus")
|
|
||||||
}
|
|
||||||
return string(modulusBlock.Bytes), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignTextDetached sign detached text type
|
// SignTextDetached sign detached text type
|
||||||
func (o *OpenPGP) SignTextDetached(plainText string, privateKey string, passphrase string, trim bool) (string, error) {
|
func (pm *PmCrypto) SignTextDetached(plainText string, privateKey string, passphrase string, trim bool) (string, error) {
|
||||||
//sign with 0x01 text
|
//sign with 0x01 text
|
||||||
var signEntity *openpgp.Entity
|
var signEntity *openpgp.Entity
|
||||||
|
|
||||||
if trim {
|
if trim {
|
||||||
plainText = trimNewlines(plainText)
|
plainText = internal.TrimNewlines(plainText)
|
||||||
}
|
}
|
||||||
|
|
||||||
signerReader := strings.NewReader(privateKey)
|
signerReader := strings.NewReader(privateKey)
|
||||||
|
|
@ -54,7 +45,7 @@ func (o *OpenPGP) SignTextDetached(plainText string, privateKey string, passphra
|
||||||
return "", errors.New("cannot sign message, signer key is not unlocked")
|
return "", errors.New("cannot sign message, signer key is not unlocked")
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: o.getTimeGenerator() }
|
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pm.getTimeGenerator() }
|
||||||
|
|
||||||
att := strings.NewReader(plainText)
|
att := strings.NewReader(plainText)
|
||||||
|
|
||||||
|
|
@ -68,12 +59,12 @@ func (o *OpenPGP) SignTextDetached(plainText string, privateKey string, passphra
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignTextDetachedBinKey ...
|
// SignTextDetachedBinKey ...
|
||||||
func (o *OpenPGP) SignTextDetachedBinKey(plainText string, privateKey []byte, passphrase string, trim bool) (string, error) {
|
func (pm *PmCrypto) SignTextDetachedBinKey(plainText string, privateKey []byte, passphrase string, trim bool) (string, error) {
|
||||||
//sign with 0x01
|
//sign with 0x01
|
||||||
var signEntity *openpgp.Entity
|
var signEntity *openpgp.Entity
|
||||||
|
|
||||||
if trim {
|
if trim {
|
||||||
plainText = trimNewlines(plainText)
|
plainText = internal.TrimNewlines(plainText)
|
||||||
}
|
}
|
||||||
|
|
||||||
signerReader := bytes.NewReader(privateKey)
|
signerReader := bytes.NewReader(privateKey)
|
||||||
|
|
@ -99,7 +90,7 @@ func (o *OpenPGP) SignTextDetachedBinKey(plainText string, privateKey []byte, pa
|
||||||
return "", errors.New("cannot sign message, singer key is not unlocked")
|
return "", errors.New("cannot sign message, singer key is not unlocked")
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: o.getTimeGenerator() }
|
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pm.getTimeGenerator() }
|
||||||
|
|
||||||
att := strings.NewReader(plainText)
|
att := strings.NewReader(plainText)
|
||||||
|
|
||||||
|
|
@ -113,7 +104,7 @@ func (o *OpenPGP) SignTextDetachedBinKey(plainText string, privateKey []byte, pa
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignBinDetached sign bin data
|
// SignBinDetached sign bin data
|
||||||
func (o *OpenPGP) SignBinDetached(plainData []byte, privateKey string, passphrase string) (string, error) {
|
func (pm *PmCrypto) SignBinDetached(plainData []byte, privateKey string, passphrase string) (string, error) {
|
||||||
//sign with 0x00
|
//sign with 0x00
|
||||||
var signEntity *openpgp.Entity
|
var signEntity *openpgp.Entity
|
||||||
|
|
||||||
|
|
@ -140,7 +131,7 @@ func (o *OpenPGP) SignBinDetached(plainData []byte, privateKey string, passphras
|
||||||
return "", errors.New("cannot sign message, singer key is not unlocked")
|
return "", errors.New("cannot sign message, singer key is not unlocked")
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: o.getTimeGenerator() }
|
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pm.getTimeGenerator() }
|
||||||
|
|
||||||
att := bytes.NewReader(plainData)
|
att := bytes.NewReader(plainData)
|
||||||
|
|
||||||
|
|
@ -154,7 +145,7 @@ func (o *OpenPGP) SignBinDetached(plainData []byte, privateKey string, passphras
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignBinDetachedBinKey ...
|
// SignBinDetachedBinKey ...
|
||||||
func (o *OpenPGP) SignBinDetachedBinKey(plainData []byte, privateKey []byte, passphrase string) (string, error) {
|
func (pm *PmCrypto) SignBinDetachedBinKey(plainData []byte, privateKey []byte, passphrase string) (string, error) {
|
||||||
//sign with 0x00
|
//sign with 0x00
|
||||||
var signEntity *openpgp.Entity
|
var signEntity *openpgp.Entity
|
||||||
|
|
||||||
|
|
@ -181,7 +172,7 @@ func (o *OpenPGP) SignBinDetachedBinKey(plainData []byte, privateKey []byte, pas
|
||||||
return "", errors.New("cannot sign message, singer key is not unlocked")
|
return "", errors.New("cannot sign message, singer key is not unlocked")
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: o.getTimeGenerator() }
|
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pm.getTimeGenerator() }
|
||||||
|
|
||||||
att := bytes.NewReader(plainData)
|
att := bytes.NewReader(plainData)
|
||||||
|
|
||||||
|
|
@ -195,7 +186,7 @@ func (o *OpenPGP) SignBinDetachedBinKey(plainData []byte, privateKey []byte, pas
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyTextSignDetached ...
|
// VerifyTextSignDetached ...
|
||||||
func (o *OpenPGP) VerifyTextSignDetached(signature string, plainText string, publicKey string, verifyTime int64) (bool, error) {
|
func (pm *PmCrypto) VerifyTextSignDetached(signature string, plainText string, publicKey string, verifyTime int64) (bool, error) {
|
||||||
|
|
||||||
pubKeyReader := strings.NewReader(publicKey)
|
pubKeyReader := strings.NewReader(publicKey)
|
||||||
|
|
||||||
|
|
@ -204,7 +195,7 @@ func (o *OpenPGP) VerifyTextSignDetached(signature string, plainText string, pub
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
plainText = trimNewlines(plainText)
|
plainText = internal.TrimNewlines(plainText)
|
||||||
|
|
||||||
origText := bytes.NewReader(bytes.NewBufferString(plainText).Bytes())
|
origText := bytes.NewReader(bytes.NewBufferString(plainText).Bytes())
|
||||||
|
|
||||||
|
|
@ -212,7 +203,7 @@ func (o *OpenPGP) VerifyTextSignDetached(signature string, plainText string, pub
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyTextSignDetachedBinKey ...
|
// VerifyTextSignDetachedBinKey ...
|
||||||
func (o *OpenPGP) VerifyTextSignDetachedBinKey(signature string, plainText string, publicKey []byte, verifyTime int64) (bool, error) {
|
func (pm *PmCrypto) VerifyTextSignDetachedBinKey(signature string, plainText string, publicKey []byte, verifyTime int64) (bool, error) {
|
||||||
|
|
||||||
pubKeyReader := bytes.NewReader(publicKey)
|
pubKeyReader := bytes.NewReader(publicKey)
|
||||||
|
|
||||||
|
|
@ -221,7 +212,7 @@ func (o *OpenPGP) VerifyTextSignDetachedBinKey(signature string, plainText strin
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
plainText = trimNewlines(plainText)
|
plainText = internal.TrimNewlines(plainText)
|
||||||
origText := bytes.NewReader(bytes.NewBufferString(plainText).Bytes())
|
origText := bytes.NewReader(bytes.NewBufferString(plainText).Bytes())
|
||||||
|
|
||||||
return verifySignature(pubKeyEntries, origText, signature, verifyTime)
|
return verifySignature(pubKeyEntries, origText, signature, verifyTime)
|
||||||
|
|
@ -235,7 +226,7 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText *bytes.Reader, s
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
config.Time = func() time.Time {
|
config.Time = func() time.Time {
|
||||||
return time.Unix(verifyTime + creationTimeOffset, 0)
|
return time.Unix(verifyTime + internal.CreationTimeOffset, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signatureReader := strings.NewReader(signature)
|
signatureReader := strings.NewReader(signature)
|
||||||
|
|
@ -272,7 +263,7 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText *bytes.Reader, s
|
||||||
|
|
||||||
|
|
||||||
// VerifyBinSignDetached ...
|
// VerifyBinSignDetached ...
|
||||||
func (o *OpenPGP) VerifyBinSignDetached(signature string, plainData []byte, publicKey string, verifyTime int64) (bool, error) {
|
func (pm *PmCrypto) VerifyBinSignDetached(signature string, plainData []byte, publicKey string, verifyTime int64) (bool, error) {
|
||||||
|
|
||||||
pubKeyReader := strings.NewReader(publicKey)
|
pubKeyReader := strings.NewReader(publicKey)
|
||||||
|
|
||||||
|
|
@ -286,7 +277,7 @@ func (o *OpenPGP) VerifyBinSignDetached(signature string, plainData []byte, publ
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyBinSignDetachedBinKey ...
|
// VerifyBinSignDetachedBinKey ...
|
||||||
func (o *OpenPGP) VerifyBinSignDetachedBinKey(signature string, plainData []byte, publicKey []byte, verifyTime int64) (bool, error) {
|
func (pm *PmCrypto) VerifyBinSignDetachedBinKey(signature string, plainData []byte, publicKey []byte, verifyTime int64) (bool, error) {
|
||||||
pubKeyReader := bytes.NewReader(publicKey)
|
pubKeyReader := bytes.NewReader(publicKey)
|
||||||
|
|
||||||
pubKeyEntries, err := openpgp.ReadKeyRing(pubKeyReader)
|
pubKeyEntries, err := openpgp.ReadKeyRing(pubKeyReader)
|
||||||
100
crypto/signature_collector.go
Normal file
100
crypto/signature_collector.go
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"golang.org/x/crypto/openpgp"
|
||||||
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"mime"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/textproto"
|
||||||
|
"proton/pmmime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SignatureCollector struct {
|
||||||
|
config *packet.Config
|
||||||
|
keyring openpgp.KeyRing
|
||||||
|
target pmmime.VisitAcceptor
|
||||||
|
signature string
|
||||||
|
verified int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSignatureCollector(targetAccepter pmmime.VisitAcceptor, keyring openpgp.KeyRing, config *packet.Config) *SignatureCollector {
|
||||||
|
return &SignatureCollector{
|
||||||
|
target: targetAccepter,
|
||||||
|
config: config,
|
||||||
|
keyring: keyring,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc *SignatureCollector) Accept(part io.Reader, header textproto.MIMEHeader, hasPlainSibling bool, isFirst, isLast bool) (err error) {
|
||||||
|
parentMediaType, params, _ := mime.ParseMediaType(header.Get("Content-Type"))
|
||||||
|
if parentMediaType == "multipart/signed" {
|
||||||
|
newPart, rawBody := pmmime.GetRawMimePart(part, "--"+params["boundary"])
|
||||||
|
var multiparts []io.Reader
|
||||||
|
var multipartHeaders []textproto.MIMEHeader
|
||||||
|
if multiparts, multipartHeaders, err = pmmime.GetMultipartParts(newPart, params); err != nil {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
hasPlainChild := false
|
||||||
|
for _, header := range multipartHeaders {
|
||||||
|
mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type"))
|
||||||
|
if mediaType == "text/plain" {
|
||||||
|
hasPlainChild = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(multiparts) != 2 {
|
||||||
|
sc.verified = notSigned
|
||||||
|
// Invalid multipart/signed format just pass along
|
||||||
|
ioutil.ReadAll(rawBody)
|
||||||
|
for i, p := range multiparts {
|
||||||
|
if err = sc.target.Accept(p, multipartHeaders[i], hasPlainChild, true, true); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// actual multipart/signed format
|
||||||
|
err = sc.target.Accept(multiparts[0], multipartHeaders[0], hasPlainChild, true, true)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO: Sunny proposed to move this also to pm-mime library
|
||||||
|
partData, _ := ioutil.ReadAll(multiparts[1])
|
||||||
|
decodedPart := pmmime.DecodeContentEncoding(bytes.NewReader(partData), multipartHeaders[1].Get("Content-Transfer-Encoding"))
|
||||||
|
buffer, err := ioutil.ReadAll(decodedPart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buffer, err = pmmime.DecodeCharset(buffer, params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sc.signature = string(buffer)
|
||||||
|
str, _ := ioutil.ReadAll(rawBody)
|
||||||
|
rawBody = bytes.NewReader(str)
|
||||||
|
if sc.keyring != nil {
|
||||||
|
_, err = openpgp.CheckArmoredDetachedSignature(sc.keyring, rawBody, bytes.NewReader(buffer), sc.config)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
sc.verified = failed
|
||||||
|
} else {
|
||||||
|
sc.verified = ok
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sc.verified = noVerifier
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sc.target.Accept(part, header, hasPlainSibling, isFirst, isLast)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ac SignatureCollector) GetSignature() string {
|
||||||
|
return ac.signature
|
||||||
|
}
|
||||||
32
crypto/time.go
Normal file
32
crypto/time.go
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateTime update cached time
|
||||||
|
func (pm *PmCrypto) UpdateTime(newTime int64) {
|
||||||
|
pm.latestServerTime = newTime
|
||||||
|
pm.latestClientTime = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetTime get latest cached time
|
||||||
|
func (pm *PmCrypto) GetTime() int64 {
|
||||||
|
return pm.getNow().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *PmCrypto) getNow() time.Time {
|
||||||
|
if pm.latestServerTime > 0 && !pm.latestClientTime.IsZero() {
|
||||||
|
// Sub is monotome, it uses a monotime time clock in this case instead of the wall clock
|
||||||
|
extrapolate := int64(pm.latestClientTime.Sub(time.Now()).Seconds())
|
||||||
|
return time.Unix(pm.latestServerTime + extrapolate, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *PmCrypto) getTimeGenerator() func() time.Time {
|
||||||
|
return func() time.Time {
|
||||||
|
return pm.getNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
dist/Android/pmcrypto-sources.jar
vendored
Normal file
BIN
dist/Android/pmcrypto-sources.jar
vendored
Normal file
Binary file not shown.
BIN
dist/Android/pmcrypto.aar
vendored
Normal file
BIN
dist/Android/pmcrypto.aar
vendored
Normal file
Binary file not shown.
29
glide.lock
generated
29
glide.lock
generated
|
|
@ -1,8 +1,10 @@
|
||||||
hash: 217e5bc8c4d3160eeddd18dda7f8f8785f1b2b7f2ca58779b94ed8fd91ab226d
|
hash: 0e0069ce69a4e3bde6233726f21a880347400808a97c2e6f7a173e4d7daea51c
|
||||||
updated: 2018-06-05T11:36:14.582087-07:00
|
updated: 2018-09-07T10:20:50.211694+02:00
|
||||||
imports:
|
imports:
|
||||||
|
- name: github.com/Sirupsen/logrus
|
||||||
|
version: 3791101e143bf0f32515ac23e831475684f61229
|
||||||
- name: golang.org/x/crypto
|
- name: golang.org/x/crypto
|
||||||
version: 4dad02e057d03c4f12a519a73d4b4f1837de135d
|
version: 9e4251120d8c43f10024d798bc6dde21d40704a0
|
||||||
repo: https://github.com/ProtonMail/crypto.git
|
repo: https://github.com/ProtonMail/crypto.git
|
||||||
subpackages:
|
subpackages:
|
||||||
- bitcurves
|
- bitcurves
|
||||||
|
|
@ -11,6 +13,8 @@ imports:
|
||||||
- curve25519
|
- curve25519
|
||||||
- ed25519
|
- ed25519
|
||||||
- ed25519/internal/edwards25519
|
- ed25519/internal/edwards25519
|
||||||
|
- internal/randutil
|
||||||
|
- internal/syscall/unix
|
||||||
- openpgp
|
- openpgp
|
||||||
- openpgp/aes/keywrap
|
- openpgp/aes/keywrap
|
||||||
- openpgp/armor
|
- openpgp/armor
|
||||||
|
|
@ -23,4 +27,23 @@ imports:
|
||||||
- openpgp/internal/encoding
|
- openpgp/internal/encoding
|
||||||
- openpgp/packet
|
- openpgp/packet
|
||||||
- openpgp/s2k
|
- openpgp/s2k
|
||||||
|
- rand
|
||||||
|
- rsa
|
||||||
|
- ssh/terminal
|
||||||
|
- name: golang.org/x/sys
|
||||||
|
version: 8cf3aee429924738c56c34bb819c4ea8273fc434
|
||||||
|
subpackages:
|
||||||
|
- unix
|
||||||
|
- windows
|
||||||
|
- name: golang.org/x/text
|
||||||
|
version: 4ae1256249243a4eb350a9a372e126557f2aa346
|
||||||
|
subpackages:
|
||||||
|
- encoding
|
||||||
|
- encoding/charmap
|
||||||
|
- encoding/internal
|
||||||
|
- encoding/internal/identifier
|
||||||
|
- transform
|
||||||
|
- name: proton/pmmime
|
||||||
|
version: 347d69204aa62d6958bcb3b9bbacccb24a36372b
|
||||||
|
repo: git@gitlab.protontech.ch:ProtonMail/go-pm-mime.git
|
||||||
testImports: []
|
testImports: []
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package: pm
|
package: proton/pmcrypto
|
||||||
import:
|
import:
|
||||||
- package: golang.org/x/crypto
|
- package: golang.org/x/crypto
|
||||||
version: v1.0.0
|
version: v1.0.0
|
||||||
repo: https://github.com/ProtonMail/crypto.git
|
repo: https://github.com/ProtonMail/crypto.git
|
||||||
|
- package: proton/pmmime
|
||||||
|
repo: git@gitlab.protontech.ch:ProtonMail/go-pm-mime.git
|
||||||
|
|
|
||||||
16
internal/armor.go
Normal file
16
internal/armor.go
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/crypto/openpgp/armor"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Unarmor(input string) (*armor.Block, error) {
|
||||||
|
io := strings.NewReader(input)
|
||||||
|
b, err := armor.Decode(io)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
|
||||||
|
}
|
||||||
25
internal/common.go
Normal file
25
internal/common.go
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitlab.com/ProtonMail/go-pm-crypto/constants"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TrimNewlines(input string) string {
|
||||||
|
var re = regexp.MustCompile(`(?m)[ \t]*$`)
|
||||||
|
return re.ReplaceAllString(input, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Amount of seconds that a signature may be created after the verify time
|
||||||
|
// Consistent with the 2 day slack allowed in the ProtonMail Email Parser
|
||||||
|
const CreationTimeOffset = int64(60 * 60 * 24 * 2)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ARMOR_HEADER_VERSION = "Pmcrypto Golang 0.0.1 (" + constants.VERSION + ")"
|
||||||
|
ARMOR_HEADER_COMMENT = "https://protonmail.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ArmorHeaders = map[string]string{
|
||||||
|
"Version": ARMOR_HEADER_VERSION,
|
||||||
|
"Comment": ARMOR_HEADER_COMMENT,
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package pm
|
package key
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -6,11 +6,12 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
|
"proton/pmcrypto/armor"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetFingerprint get a armored public key fingerprint
|
// GetFingerprint get a armored public key fingerprint
|
||||||
func GetFingerprint(publicKey string) (string, error) {
|
func GetFingerprint(publicKey string) (string, error) {
|
||||||
rawPubKey, err := UnArmor(publicKey)
|
rawPubKey, err := armor.Unarmor(publicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
78
key/key.go
Normal file
78
key/key.go
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
package key
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"golang.org/x/crypto/openpgp"
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
|
"bytes"
|
||||||
|
"proton/pmcrypto/armor"
|
||||||
|
)
|
||||||
|
|
||||||
|
//CheckPassphrase check is private key passphrase ok
|
||||||
|
func CheckPassphrase(privateKey string, passphrase string) bool {
|
||||||
|
privKeyReader := strings.NewReader(privateKey)
|
||||||
|
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var keys []*packet.PrivateKey
|
||||||
|
|
||||||
|
for _, e := range entries {
|
||||||
|
keys = append(keys, e.PrivateKey)
|
||||||
|
}
|
||||||
|
var decryptError error
|
||||||
|
var n int
|
||||||
|
for _, key := range keys {
|
||||||
|
if !key.Encrypted {
|
||||||
|
continue // Key already decrypted
|
||||||
|
}
|
||||||
|
if decryptError = key.Decrypt([]byte(passphrase)); decryptError == nil {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PublicKey get a public key from a private key
|
||||||
|
func PublicKey(privateKey string) (string, error) {
|
||||||
|
privKeyReader := strings.NewReader(privateKey)
|
||||||
|
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var outBuf bytes.Buffer
|
||||||
|
for _, e := range entries {
|
||||||
|
e.Serialize(&outBuf)
|
||||||
|
}
|
||||||
|
|
||||||
|
outString, err := armor.ArmorWithType(outBuf.Bytes(), armor.PUBLIC_KEY_HEADER)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return outString, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublicKeyBinOut get a public key from a private key
|
||||||
|
func PublicKeyBinOut(privateKey string) ([]byte, error) {
|
||||||
|
privKeyReader := strings.NewReader(privateKey)
|
||||||
|
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var outBuf bytes.Buffer
|
||||||
|
for _, e := range entries {
|
||||||
|
e.Serialize(&outBuf)
|
||||||
|
}
|
||||||
|
|
||||||
|
return outBuf.Bytes(), nil
|
||||||
|
}
|
||||||
30
models/models.go
Normal file
30
models/models.go
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
//EncryptedSplit when encrypt attachemt
|
||||||
|
type EncryptedSplit struct {
|
||||||
|
DataPacket []byte
|
||||||
|
KeyPacket []byte
|
||||||
|
Algo string
|
||||||
|
}
|
||||||
|
|
||||||
|
//SessionSplit split session
|
||||||
|
type SessionSplit struct {
|
||||||
|
Session []byte
|
||||||
|
Algo string
|
||||||
|
}
|
||||||
|
|
||||||
|
//EncryptedSigned encrypt_sign_package
|
||||||
|
type EncryptedSigned struct {
|
||||||
|
Encrypted string
|
||||||
|
Signature string
|
||||||
|
}
|
||||||
|
|
||||||
|
//DecryptSignedVerify decrypt_sign_verify
|
||||||
|
type DecryptSignedVerify struct {
|
||||||
|
//clear text
|
||||||
|
Plaintext string
|
||||||
|
//bitmask verify status : 0
|
||||||
|
Verify int
|
||||||
|
//error message if verify failed
|
||||||
|
Message string
|
||||||
|
}
|
||||||
32
time.go
32
time.go
|
|
@ -1,32 +0,0 @@
|
||||||
package pm
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UpdateTime update cached time
|
|
||||||
func (o *OpenPGP) UpdateTime(newTime int64) {
|
|
||||||
o.latestServerTime = newTime
|
|
||||||
o.latestClientTime = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
//GetTime get latest cached time
|
|
||||||
func (o *OpenPGP) GetTime() int64 {
|
|
||||||
return o.getNow().Unix()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *OpenPGP) getNow() time.Time {
|
|
||||||
if o.latestServerTime > 0 && !o.latestClientTime.IsZero() {
|
|
||||||
// Sub is monotome, it uses a monotime time clock in this case instead of the wall clock
|
|
||||||
extrapolate := int64(o.latestClientTime.Sub(time.Now()).Seconds())
|
|
||||||
return time.Unix(o.latestServerTime + extrapolate, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *OpenPGP) getTimeGenerator() func() time.Time {
|
|
||||||
return func() time.Time {
|
|
||||||
return o.getNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package pm
|
|
||||||
|
|
||||||
// Version get current lib version
|
|
||||||
func Version() string {
|
|
||||||
return "ddacebe0"
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue