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" using: "composite"
steps: steps:
- name: Checkout gopenpgp - name: Checkout gopenpgp
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
ref: ${{ inputs.gopenpgp-ref }} ref: ${{ inputs.gopenpgp-ref }}
path: gopenpgp path: gopenpgp
@ -32,7 +32,7 @@ runs:
with: with:
go-version: ^1.18 go-version: ^1.18
- name: Check out gosop - name: Check out gosop
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
repository: ProtonMail/gosop repository: ProtonMail/gosop
ref: ${{ env.GOSOP_BRANCH_REF}} ref: ${{ env.GOSOP_BRANCH_REF}}

View file

@ -30,7 +30,7 @@ jobs:
link-to-sdk: true link-to-sdk: true
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Build - name: Build
run: | run: |
@ -41,7 +41,7 @@ jobs:
find dist find dist
- name: Upload Android artifacts - name: Upload Android artifacts
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: Android build name: Android build
path: dist/android path: dist/android

View file

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out repo - name: Check out repo
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up latest golang - name: Set up latest golang
uses: actions/setup-go@v3 uses: actions/setup-go@v3
@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out repo - name: Check out repo
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up Go 1.17 - name: Set up Go 1.17
uses: actions/setup-go@v3 uses: actions/setup-go@v3
@ -44,7 +44,7 @@ jobs:
- uses: actions/setup-go@v3 - uses: actions/setup-go@v3
with: with:
go-version: 1.17 go-version: 1.17
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v3 uses: golangci/golangci-lint-action@v3
with: with:

View file

@ -15,7 +15,7 @@ jobs:
- name: Set up xcode 14.3 - name: Set up xcode 14.3
uses: maxim-lobanov/setup-xcode@v1 uses: maxim-lobanov/setup-xcode@v1
with: with:
xcode-version: 14.3 xcode-version: 15.3.0
id: xcode id: xcode
- name: Set up Go 1.x - name: Set up Go 1.x
@ -25,7 +25,7 @@ jobs:
id: go id: go
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Build - name: Build
env: env:
@ -35,7 +35,7 @@ jobs:
find dist find dist
- name: Upload xcframework - name: Upload xcframework
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: gopenpgp.xcframework name: gopenpgp.xcframework
path: dist/apple/gopenpgp.xcframework path: dist/apple/gopenpgp.xcframework

View file

@ -11,14 +11,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Build gosop from branch - name: Build gosop from branch
uses: ./.github/actions/build-gosop uses: ./.github/actions/build-gosop
with: with:
binary-location: ./gosop-${{ github.sha }} binary-location: ./gosop-${{ github.sha }}
# Upload as artifact # Upload as artifact
- name: Upload gosop artifact - name: Upload gosop artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: gosop-${{ github.sha }} name: gosop-${{ github.sha }}
path: ./gosop-${{ github.sha }} path: ./gosop-${{ github.sha }}
@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Build gosop from branch - name: Build gosop from branch
uses: ./.github/actions/build-gosop uses: ./.github/actions/build-gosop
with: with:
@ -36,7 +36,7 @@ jobs:
binary-location: ./gosop-target binary-location: ./gosop-target
# Upload as artifact # Upload as artifact
- name: Upload gosop-target artifact - name: Upload gosop-target artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: gosop-target name: gosop-target
path: ./gosop-target path: ./gosop-target
@ -55,10 +55,10 @@ jobs:
- build-gosop-target - build-gosop-target
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
# Fetch gosop from target # Fetch gosop from target
- name: Download gosop-target - name: Download gosop-target
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: gosop-target name: gosop-target
# Test gosop-target # Test gosop-target
@ -68,7 +68,7 @@ jobs:
run: ./gosop-target version --extended run: ./gosop-target version --extended
# Fetch gosop from branch # Fetch gosop from branch
- name: Download gosop-branch - name: Download gosop-branch
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: gosop-${{ github.sha }} name: gosop-${{ github.sha }}
- name: Rename gosop-branch - name: Rename gosop-branch
@ -94,12 +94,12 @@ jobs:
RESULTS_HTML: .github/test-suite/test-suite-results.html RESULTS_HTML: .github/test-suite/test-suite-results.html
# Upload results # Upload results
- name: Upload test results json artifact - name: Upload test results json artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: test-suite-results.json name: test-suite-results.json
path: .github/test-suite/test-suite-results.json path: .github/test-suite/test-suite-results.json
- name: Upload test results html artifact - name: Upload test results html artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: test-suite-results.html name: test-suite-results.html
path: .github/test-suite/test-suite-results.html path: .github/test-suite/test-suite-results.html
@ -110,10 +110,10 @@ jobs:
needs: test-suite needs: test-suite
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Download test results json artifact - name: Download test results json artifact
id: download-test-results id: download-test-results
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: test-suite-results.json name: test-suite-results.json
- name: Compare with baseline - 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/), 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). 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 ## [2.8.0-alpha.1] 2024-04-09
### Added ### Added

View file

@ -3,7 +3,7 @@ package constants
// Constants for armored data. // Constants for armored data.
const ( const (
ArmorHeaderVersion = "GopenPGP 2.8.0" ArmorHeaderVersion = "GopenPGP 2.8.1"
ArmorHeaderComment = "https://gopenpgp.org" ArmorHeaderComment = "https://gopenpgp.org"
PGPMessageHeader = "PGP MESSAGE" PGPMessageHeader = "PGP MESSAGE"
PGPSignatureHeader = "PGP SIGNATURE" PGPSignatureHeader = "PGP SIGNATURE"

View file

@ -1,3 +1,3 @@
package constants 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) 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. // GetSHA256Fingerprints computes the SHA256 fingerprints of the key and subkeys.
func (key *Key) GetSHA256Fingerprints() (fingerprints []string) { 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 { for _, sub := range key.entity.Subkeys {
fingerprints = append(fingerprints, hex.EncodeToString(getSHA256FingerprintBytes(sub.PublicKey))) 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.Len(t, sha256Fingerprints, 2)
assert.Exactly(t, "d9ac0b857da6d2c8be985b251a9e3db31e7a1d2d832d1f07ebe838a9edce9c24", sha256Fingerprints[0]) assert.Exactly(t, "d9ac0b857da6d2c8be985b251a9e3db31e7a1d2d832d1f07ebe838a9edce9c24", sha256Fingerprints[0])
assert.Exactly(t, "203dfba1f8442c17e59214d9cd11985bfc5cc8721bb4a71740dd5507e58a1a0d", sha256Fingerprints[1]) assert.Exactly(t, "203dfba1f8442c17e59214d9cd11985bfc5cc8721bb4a71740dd5507e58a1a0d", sha256Fingerprints[1])
assert.Exactly(t, "d9ac0b857da6d2c8be985b251a9e3db31e7a1d2d832d1f07ebe838a9edce9c24", publicKey.GetSHA256Fingerprint())
} }
func TestGetEntity(t *testing.T) { func TestGetEntity(t *testing.T) {

View file

@ -17,11 +17,15 @@ import (
"github.com/ProtonMail/gopenpgp/v2/internal" "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{ var allowedHashes = []crypto.Hash{
crypto.SHA224, crypto.SHA224,
crypto.SHA256, crypto.SHA256,
crypto.SHA384, crypto.SHA384,
crypto.SHA512, crypto.SHA512,
crypto.SHA3_256,
crypto.SHA3_512,
} }
// SignatureVerificationError is returned from Decrypt and VerifyDetached // 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") t.Fatal("Packet was not a signature")
} }
notations := sig.Notations notations := sig.Notations
if len(notations) != 1 { if len(notations) != 2 {
t.Fatal("Wrong number of notations") t.Fatal("Wrong number of notations")
} }
notation := notations[0] notation := notations[0]
@ -344,7 +344,7 @@ func Test_SignDetachedWithCriticalContext(t *testing.T) {
t.Fatal("Packet was not a signature") t.Fatal("Packet was not a signature")
} }
notations := sig.Notations notations := sig.Notations
if len(notations) != 1 { if len(notations) != 2 {
t.Fatal("Wrong number of notations") t.Fatal("Wrong number of notations")
} }
notation := notations[0] notation := notations[0]

4
go.mod
View file

@ -3,7 +3,7 @@ module github.com/ProtonMail/gopenpgp/v2
go 1.17 go 1.17
require ( 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/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
@ -18,3 +18,5 @@ require (
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // 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.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
github.com/ProtonMail/go-crypto v1.1.0-alpha.1/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= 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 h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k=
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= 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= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=

View file

@ -4,8 +4,134 @@ package helper
import ( import (
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/pkg/errors" "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. // EncryptMessageWithPassword encrypts a string with a passphrase using AES256.
func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext string, err error) { func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext string, err error) {
var pgpMessage *crypto.PGPMessage var pgpMessage *crypto.PGPMessage