Compare commits
10 commits
4e8fad59d6
...
4e27e861c7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e27e861c7 | ||
|
|
41389bb5b0 | ||
|
|
81fdf286c5 | ||
|
|
4340541fe0 | ||
|
|
4c05fbeec7 | ||
|
|
113e32660b | ||
|
|
a3608a3d8d | ||
|
|
5ec8559b90 | ||
|
|
1136c7d026 | ||
|
|
dec9c18fc6 |
15 changed files with 183 additions and 29 deletions
4
.github/actions/build-gosop/action.yml
vendored
4
.github/actions/build-gosop/action.yml
vendored
|
|
@ -16,7 +16,7 @@ runs:
|
|||
using: "composite"
|
||||
steps:
|
||||
- name: Checkout gopenpgp
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.gopenpgp-ref }}
|
||||
path: gopenpgp
|
||||
|
|
@ -32,7 +32,7 @@ runs:
|
|||
with:
|
||||
go-version: ^1.18
|
||||
- name: Check out gosop
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ProtonMail/gosop
|
||||
ref: ${{ env.GOSOP_BRANCH_REF}}
|
||||
|
|
|
|||
4
.github/workflows/android.yml
vendored
4
.github/workflows/android.yml
vendored
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
link-to-sdk: true
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
|
@ -41,7 +41,7 @@ jobs:
|
|||
find dist
|
||||
|
||||
- name: Upload Android artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Android build
|
||||
path: dist/android
|
||||
|
|
|
|||
6
.github/workflows/go.yml
vendored
6
.github/workflows/go.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up latest golang
|
||||
uses: actions/setup-go@v3
|
||||
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go 1.17
|
||||
uses: actions/setup-go@v3
|
||||
|
|
@ -44,7 +44,7 @@ jobs:
|
|||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.17
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
|
|
|
|||
6
.github/workflows/ios.yml
vendored
6
.github/workflows/ios.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
- name: Set up xcode 14.3
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: 14.3
|
||||
xcode-version: 15.3.0
|
||||
id: xcode
|
||||
|
||||
- name: Set up Go 1.x
|
||||
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
id: go
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
|
|
@ -35,7 +35,7 @@ jobs:
|
|||
find dist
|
||||
|
||||
- name: Upload xcframework
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gopenpgp.xcframework
|
||||
path: dist/apple/gopenpgp.xcframework
|
||||
|
|
|
|||
22
.github/workflows/sop-test-suite.yml
vendored
22
.github/workflows/sop-test-suite.yml
vendored
|
|
@ -11,14 +11,14 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build gosop from branch
|
||||
uses: ./.github/actions/build-gosop
|
||||
with:
|
||||
binary-location: ./gosop-${{ github.sha }}
|
||||
# Upload as artifact
|
||||
- name: Upload gosop artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gosop-${{ github.sha }}
|
||||
path: ./gosop-${{ github.sha }}
|
||||
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build gosop from branch
|
||||
uses: ./.github/actions/build-gosop
|
||||
with:
|
||||
|
|
@ -36,7 +36,7 @@ jobs:
|
|||
binary-location: ./gosop-target
|
||||
# Upload as artifact
|
||||
- name: Upload gosop-target artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gosop-target
|
||||
path: ./gosop-target
|
||||
|
|
@ -55,10 +55,10 @@ jobs:
|
|||
- build-gosop-target
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
# Fetch gosop from target
|
||||
- name: Download gosop-target
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: gosop-target
|
||||
# Test gosop-target
|
||||
|
|
@ -68,7 +68,7 @@ jobs:
|
|||
run: ./gosop-target version --extended
|
||||
# Fetch gosop from branch
|
||||
- name: Download gosop-branch
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: gosop-${{ github.sha }}
|
||||
- name: Rename gosop-branch
|
||||
|
|
@ -94,12 +94,12 @@ jobs:
|
|||
RESULTS_HTML: .github/test-suite/test-suite-results.html
|
||||
# Upload results
|
||||
- name: Upload test results json artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-suite-results.json
|
||||
path: .github/test-suite/test-suite-results.json
|
||||
- name: Upload test results html artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-suite-results.html
|
||||
path: .github/test-suite/test-suite-results.html
|
||||
|
|
@ -110,10 +110,10 @@ jobs:
|
|||
needs: test-suite
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Download test results json artifact
|
||||
id: download-test-results
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: test-suite-results.json
|
||||
- name: Compare with baseline
|
||||
|
|
|
|||
15
CHANGELOG.md
15
CHANGELOG.md
|
|
@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.8.1] 2024-11-25
|
||||
### Changed
|
||||
- Update go-crypto to `1.1.3`.
|
||||
|
||||
## [2.8.0] 2024-10-07
|
||||
### Changed
|
||||
- Update go-crypto to `1.1.0`.
|
||||
|
||||
## [2.8.0-beta.0] 2024-10-01
|
||||
### Added
|
||||
- Add `GetSHA256Fingerprint` method to `Key`.
|
||||
|
||||
### Changed
|
||||
- Update go-crypto to `1.1.0-beta.0`.
|
||||
|
||||
## [2.8.0-alpha.1] 2024-04-09
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package constants
|
|||
|
||||
// Constants for armored data.
|
||||
const (
|
||||
ArmorHeaderVersion = "GopenPGP 2.8.0"
|
||||
ArmorHeaderVersion = "GopenPGP 2.8.1"
|
||||
ArmorHeaderComment = "https://gopenpgp.org"
|
||||
PGPMessageHeader = "PGP MESSAGE"
|
||||
PGPSignatureHeader = "PGP SIGNATURE"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
package constants
|
||||
|
||||
const Version = "2.8.0"
|
||||
const Version = "2.8.1"
|
||||
|
|
|
|||
|
|
@ -365,9 +365,14 @@ func (key *Key) GetFingerprint() string {
|
|||
return hex.EncodeToString(key.entity.PrimaryKey.Fingerprint)
|
||||
}
|
||||
|
||||
// GetSHA256Fingerprint computes the SHA256 fingerprint of the primary key.
|
||||
func (key *Key) GetSHA256Fingerprint() (fingerprint string) {
|
||||
return hex.EncodeToString(getSHA256FingerprintBytes(key.entity.PrimaryKey))
|
||||
}
|
||||
|
||||
// GetSHA256Fingerprints computes the SHA256 fingerprints of the key and subkeys.
|
||||
func (key *Key) GetSHA256Fingerprints() (fingerprints []string) {
|
||||
fingerprints = append(fingerprints, hex.EncodeToString(getSHA256FingerprintBytes(key.entity.PrimaryKey)))
|
||||
fingerprints = append(fingerprints, key.GetSHA256Fingerprint())
|
||||
for _, sub := range key.entity.Subkeys {
|
||||
fingerprints = append(fingerprints, hex.EncodeToString(getSHA256FingerprintBytes(sub.PublicKey)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -374,6 +374,8 @@ func TestGetSHA256FingerprintsV4(t *testing.T) {
|
|||
assert.Len(t, sha256Fingerprints, 2)
|
||||
assert.Exactly(t, "d9ac0b857da6d2c8be985b251a9e3db31e7a1d2d832d1f07ebe838a9edce9c24", sha256Fingerprints[0])
|
||||
assert.Exactly(t, "203dfba1f8442c17e59214d9cd11985bfc5cc8721bb4a71740dd5507e58a1a0d", sha256Fingerprints[1])
|
||||
|
||||
assert.Exactly(t, "d9ac0b857da6d2c8be985b251a9e3db31e7a1d2d832d1f07ebe838a9edce9c24", publicKey.GetSHA256Fingerprint())
|
||||
}
|
||||
|
||||
func TestGetEntity(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -17,11 +17,15 @@ import (
|
|||
"github.com/ProtonMail/gopenpgp/v2/internal"
|
||||
)
|
||||
|
||||
// allowedHashes stores the allowed OpenPGP hashes that can be used in a
|
||||
// message signature hash.
|
||||
var allowedHashes = []crypto.Hash{
|
||||
crypto.SHA224,
|
||||
crypto.SHA256,
|
||||
crypto.SHA384,
|
||||
crypto.SHA512,
|
||||
crypto.SHA3_256,
|
||||
crypto.SHA3_512,
|
||||
}
|
||||
|
||||
// SignatureVerificationError is returned from Decrypt and VerifyDetached
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ func Test_SignDetachedWithNonCriticalContext(t *testing.T) {
|
|||
t.Fatal("Packet was not a signature")
|
||||
}
|
||||
notations := sig.Notations
|
||||
if len(notations) != 1 {
|
||||
if len(notations) != 2 {
|
||||
t.Fatal("Wrong number of notations")
|
||||
}
|
||||
notation := notations[0]
|
||||
|
|
@ -344,7 +344,7 @@ func Test_SignDetachedWithCriticalContext(t *testing.T) {
|
|||
t.Fatal("Packet was not a signature")
|
||||
}
|
||||
notations := sig.Notations
|
||||
if len(notations) != 1 {
|
||||
if len(notations) != 2 {
|
||||
t.Fatal("Wrong number of notations")
|
||||
}
|
||||
notation := notations[0]
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -3,7 +3,7 @@ module github.com/ProtonMail/gopenpgp/v2
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/ProtonMail/go-crypto v1.1.0-alpha.1
|
||||
github.com/ProtonMail/go-crypto v1.1.3
|
||||
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
|
|
@ -18,3 +18,5 @@ require (
|
|||
golang.org/x/text v0.14.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
)
|
||||
|
||||
replace github.com/ProtonMail/go-crypto => github.com/mssun/go-crypto v1.1.3-mssun-passforios
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -1,5 +1,5 @@
|
|||
github.com/ProtonMail/go-crypto v1.1.0-alpha.1 h1:iKLDnKGL+3u4Q5OjYgixAxWdkkGBPidCQumqVryUgtY=
|
||||
github.com/ProtonMail/go-crypto v1.1.0-alpha.1/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
|
||||
github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
|
|
|
|||
126
helper/helper.go
126
helper/helper.go
|
|
@ -4,8 +4,134 @@ package helper
|
|||
import (
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/pkg/errors"
|
||||
goerrors "errors"
|
||||
pgpErrors "github.com/ProtonMail/go-crypto/openpgp/errors"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"io"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func PassGetEncryptedMPI1(pgpMessage *crypto.PGPMessage) (encryptedMPI1 []byte, err error) {
|
||||
var p packet.Packet
|
||||
packets := packet.NewReader(pgpMessage.NewReader())
|
||||
var mpi1 []byte
|
||||
|
||||
Loop1:
|
||||
for {
|
||||
if p, err = packets.Next(); goerrors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
|
||||
switch p := p.(type) {
|
||||
case *packet.EncryptedKey:
|
||||
mpi1 = p.GetEncryptedMPI1()
|
||||
break Loop1
|
||||
}
|
||||
}
|
||||
|
||||
return mpi1, nil
|
||||
}
|
||||
|
||||
func PassGetEncryptedMPI2(pgpMessage *crypto.PGPMessage) (encryptedMPI2 []byte, err error) {
|
||||
var p packet.Packet
|
||||
packets := packet.NewReader(pgpMessage.NewReader())
|
||||
var mpi2 []byte
|
||||
|
||||
Loop1:
|
||||
for {
|
||||
if p, err = packets.Next(); goerrors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
|
||||
switch p := p.(type) {
|
||||
case *packet.EncryptedKey:
|
||||
mpi2 = p.GetEncryptedMPI2()
|
||||
break Loop1
|
||||
}
|
||||
}
|
||||
|
||||
return mpi2, nil
|
||||
}
|
||||
|
||||
|
||||
func PassGetHexSubkeyIDsJSON(key *crypto.Key) []byte {
|
||||
subKeys := key.GetEntity().Subkeys
|
||||
hexSubkeyIDs := make([]string, len(subKeys))
|
||||
for i, subKey := range subKeys {
|
||||
hexSubkeyIDs[i] = fmt.Sprintf("%016v", strconv.FormatUint(subKey.PublicKey.KeyId, 16))
|
||||
}
|
||||
|
||||
result, err := json.Marshal(hexSubkeyIDs)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
func PassDecryptWithSessionKey(pgpMessage *crypto.PGPMessage, sk *crypto.SessionKey) (plain_message *crypto.PlainMessage, err error) {
|
||||
var p packet.Packet
|
||||
packets := packet.NewReader(pgpMessage.NewReader())
|
||||
var edp packet.EncryptedDataPacket
|
||||
|
||||
Loop1:
|
||||
for {
|
||||
if p, err = packets.Next(); goerrors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
|
||||
switch p := p.(type) {
|
||||
case *packet.SymmetricallyEncrypted, *packet.AEADEncrypted:
|
||||
edp = p.(packet.EncryptedDataPacket)
|
||||
break Loop1
|
||||
}
|
||||
}
|
||||
|
||||
var decrypted io.ReadCloser
|
||||
f, err := sk.GetCipherFunc()
|
||||
decrypted, err = edp.Decrypt(f, sk.Key)
|
||||
packets.Push(decrypted)
|
||||
|
||||
md := new(openpgp.MessageDetails)
|
||||
Loop2:
|
||||
for {
|
||||
if p, err = packets.Next(); goerrors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
switch p := p.(type) {
|
||||
case *packet.Compressed:
|
||||
packets.Push(p.Body)
|
||||
case *packet.LiteralData:
|
||||
md.LiteralData = p
|
||||
md.UnverifiedBody = md.LiteralData.Body
|
||||
break Loop2
|
||||
}
|
||||
}
|
||||
|
||||
messageBuf := bytes.NewBuffer(nil)
|
||||
_, err = io.Copy(messageBuf, md.UnverifiedBody)
|
||||
if errors.Is(err, pgpErrors.ErrMDCHashMismatch) {
|
||||
// This MDC error may also be triggered if the password is correct, but the encrypted data was corrupted.
|
||||
// To avoid confusion, we do not inform the user about the second possibility.
|
||||
return nil, errors.New("gopenpgp: wrong password in symmetric decryption")
|
||||
}
|
||||
if err != nil {
|
||||
// Parsing errors after decryption, triggered before parsing the MDC packet, are also usually the result of wrong password
|
||||
return nil, errors.New("gopenpgp: error in reading password protected message: wrong password or malformed message")
|
||||
}
|
||||
|
||||
return &crypto.PlainMessage{
|
||||
Data: messageBuf.Bytes(),
|
||||
TextType: !md.LiteralData.IsBinary,
|
||||
Filename: md.LiteralData.FileName,
|
||||
Time: md.LiteralData.Time,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// EncryptMessageWithPassword encrypts a string with a passphrase using AES256.
|
||||
func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext string, err error) {
|
||||
var pgpMessage *crypto.PGPMessage
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue