Compare commits

...

10 commits

Author SHA1 Message Date
Lysann Tranvouez
4e27e861c7 add PassGetHexSubkeyIDsJSON helper for passforios 2026-03-10 21:39:35 +01:00
Mingshen Sun
41389bb5b0 Fix cache issue 2024-12-14 14:46:50 -08:00
Mingshen Sun
81fdf286c5 Update gocrypto 2024-12-14 12:07:16 -08:00
Mingshen Sun
4340541fe0 Patch for passforios
- Add passforios helper function
- Update go-crypto branch
2024-12-14 12:00:57 -08:00
Lukas Burkhalter
4c05fbeec7
chore: Prepare release 2.8.1 (#317) 2024-11-26 11:55:49 +01:00
Lukas Burkhalter
113e32660b
chore: Prepare release v2.8.0 (#309) 2024-11-07 17:00:51 +01:00
Lukas Burkhalter
a3608a3d8d
Add SHA3 to allowed signature hashes (#304) 2024-10-29 11:39:45 +01:00
Lukas Burkhalter
5ec8559b90
chore: Prepare pre-release v2.8.0-beta.0 (#302) 2024-10-01 16:55:59 +02:00
Lukas Burkhalter
1136c7d026
feat: Add SHA256 fingerprint getter (#299)
* feat: Add SHA256 fingerprint getter to key
2024-09-26 12:03:48 +02:00
Lukas Burkhalter
dec9c18fc6
ci: Update github workflow actions (#298)
- update actions/download-artifact to v4
- update actions/checkout to v4
- update actions/upload-artifact to v4
2024-09-20 10:33:44 +02:00
15 changed files with 183 additions and 29 deletions

View file

@ -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}}

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -1,3 +1,3 @@
package constants
const Version = "2.8.0"
const Version = "2.8.1"

View file

@ -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)))
}

View file

@ -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) {

View file

@ -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

View file

@ -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
View file

@ -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
View file

@ -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=

View file

@ -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