jx/internal/resource/openpgp_signature_test.go

679 lines
24 KiB
Go

// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package resource
import (
"context"
"github.com/stretchr/testify/assert"
"testing"
"fmt"
"decl/internal/data"
"decl/internal/folio"
"decl/internal/codec"
"decl/internal/ext"
"log"
"io"
"os"
"bytes"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/armor"
"log/slog"
"path/filepath"
)
var mockKeyRingPassphraseConfig MockConfigValueGetter = func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}
func DataKeyRing(uri folio.URI) (folio.ReferenceMapper[*folio.Declaration], folio.URI) {
var err error
var reader io.ReadCloser
searchPath := folio.NewSearchPath(folio.ConfigKey("system.importpath").GetStringSlice())
if u := uri.Parse().(*folio.ParsedURI); u != nil {
projectPath := filepath.Dir(filepath.Join(u.Hostname(), u.Path))
if err := searchPath.AddPath(projectPath); err != nil {
panic(err)
}
}
if reader, err = uri.ContentReaderStream(); err == nil {
keyRingDecl := folio.NewDeclaration()
if err = keyRingDecl.LoadReader(reader, codec.FormatYaml); err == nil {
keyRing := keyRingDecl.Resource()
testKeyRingResource := keyRing.(*OpenPGPKeyRing)
testKeyRingResource.KeyRingRef.FindIn(searchPath)
keyRing.UseConfig(mockKeyRingPassphraseConfig)
keyRing.Read(context.Background())
if testKeyRingResource.entityList[0].PrivateKey == nil {
log.Fatal("Keyring does not contain a private key")
}
testKeyRingResource.Resources = folio.NewResourceMapper()
testKeyRingResource.Resources.Set(folio.URI(keyRing.URI()), keyRingDecl)
return testKeyRingResource.Resources, folio.URI(testKeyRingResource.URI())
}
}
log.Fatal(err)
return nil, ""
}
func NewTestUserKeys(name string, comment string, email string) (folio.ReferenceMapper[*folio.Declaration], folio.URI) {
uri := fmt.Sprintf("openpgp-keyring://%s/%s/%s", name, comment, email)
keyRingDecl := folio.NewDeclaration()
keyRingDecl.NewResource(&uri)
ctx := context.Background()
declarationAttributes := fmt.Sprintf(`
name: %s
comment: %s
email: %s
keyringref: file://%s/keyring_%s.asc
`, name, comment, email, string(TempDir), name)
testKeyRing := keyRingDecl.Resource()
if e := testKeyRing.LoadString(declarationAttributes, codec.FormatYaml); e != nil {
log.Fatal(e)
}
testKeyRing.UseConfig(mockKeyRingPassphraseConfig)
if err := testKeyRing.Create(ctx); err != nil {
log.Fatal(err)
}
testKeyRingResource := testKeyRing.(*OpenPGPKeyRing)
if testKeyRingResource.entityList[0].PrivateKey == nil {
log.Fatal("Keyring does not contain a private key")
}
testKeyRingResource.Resources = folio.NewResourceMapper()
testKeyRingResource.Resources.Set(folio.URI(uri), keyRingDecl)
return testKeyRingResource.Resources, folio.URI(uri)
}
func KeyRingTestUser1() (folio.ReferenceMapper[*folio.Declaration], folio.URI) {
name := "TestUser1"
comment := "TestUser1"
email := "testuser@rosskeen.house"
if e := TempDir.CreateFile("keyring_TestUser1.asc", `
-----BEGIN PGP PRIVATE KEY BLOCK-----
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
=BAfD
-----END PGP PRIVATE KEY BLOCK-----
-----BEGIN PGP PUBLIC KEY BLOCK-----
xsBNBGhI/VUBCADDVSm3mKY5JsncMMJFV0zELMrmip7dkK3vvMvVWVmMHiC4akDH
WPxUdWNQPjE2e5HGF9Ebg0c7gu634VG470MnTzFdPV6f5zA+yJfdKrLq7gpl9QGW
jFLIeK/l4xc+MIpOE1rD9WqYUUw2IYY8YANYq4yB36rq41VuZps/adI9Go5IhfcU
3SVb7o7pa/gWE0FVu9ze31j2agC8FIKHgB++7bmYgbAQz5Qi1qgtG0Kn25QUacJ6
Akm2+h4w3SQCR6HLRV2BO29x9mFBszf2KQ7DW2VNiGyUuQQ3m8v2ZidG/11ff6U6
ad5tvr/8sYr5jOnKEJyDP9v9yQ04cU94GmsPABEBAAHNL1Rlc3RVc2VyMSAoVGVz
dFVzZXIxKSA8dGVzdHVzZXJAcm9zc2tlZW4uaG91c2U+wsCKBBMBCAA+BQJoSP1V
CRDfB5I2FtNl1xYhBADOnA8Aah3FXyl/m98HkjYW02XXAhsDAh4BAhkBAgsHAhUI
AxYAAgMnBwIAAGKLB/9whwgfLkoTYI+Q0Te2uZXl7FPyW0t4tbUSoI1aiVw+ymND
V+wuqYsjYDob2MyK/TAFkSCqZhBIRbGLRJtwzQwkF/amGuelHSSBX3LdxK/sp2UU
+zv/NBEP1LlUNKchuxpdBPYjKHdbOLPoKqFfdCujSxpWTIeKCwvnDtuP+PlsjUgc
afxMx+cVwe77AZ1Fi5CBD9Dr7nNsLovywrSiszyVh5eT0pbcu8Elf5oYQNT1q3ms
aqrw95shlGQiwVgrfTvRCDeZnKafHwMUoh48otsNI9aS0HpChi+JNd+PLe/Wlsj5
x+q0sHc+5/24zQvN0Wx9fPE4/7z8Pr+CUhAxjI7hzsBNBGhI/VUBCACfahoi2GRx
OfOqJ4ZN8Te+4bJeOQdzTofAisfCU736q+MvEKtAuY72vzWdERWpn7XABmtkfII8
Xyya8iHKuEGCETy0YoZ15GLBgSHhLnlN2U/4BkrUjGvUjZWquW22gfFB1q8ZdSGw
pg8hrspY/b+nnAGdawq+hfE6YRQTmG5tkBrctxfxglBnKzezmL1a3arTHWf2SRlL
eAWNI4sACryP/5plD6+9Z9YXTKeDlXnga6BzB80y7F2g0cPdtX20dWAGx4irq2I2
SxlABvWMZrdm2Upr6yLHD2zTpbf1FkKFUw9j0lrL1fMq0/j9zbKJsTh6CtOlF04s
AeoEV9SZ36GvABEBAAHCwHYEGAEIACoFAmhI/VUJEN8HkjYW02XXFiEEAM6cDwBq
HcVfKX+b3weSNhbTZdcCGwwAAFxWB/9Af7qpYKldDz5iNYQluFoPfyHAVlOpiakf
hvnu7hijTEgB1frByKu2m+k4m7gANBgfWldsYi1feWBVn6fspXuCc0k7opmQgol7
ueTrsGnNB7U0l14HcKSTLZ2c/Jt7ZS6aXXjxpYPq0/5lt8+5sRkXxHI9HhAx6gK/
RJCNITRt/V/gT4YWWbz8VHgkPIfHFsjr8brVhm4V/+JKZAG4eSNQp4QrTpdIjdfa
1rd91qffyrWhPNTQErE2jFOXSU/OojdDjGJ7pwr0qj4FHACVL3/oqYog2NrUWf92
QcwwWrEZNZUpJEMUB5q+tOoZ40ll0A8lsvABULZDqWveYpRQF+rQ
=jBvZ
-----END PGP PUBLIC KEY BLOCK-----
`); e != nil {
log.Fatal(e)
}
uri := fmt.Sprintf("openpgp-keyring://%s/%s/%s", name, comment, email)
keyRingDecl := folio.NewDeclaration()
keyRingDecl.NewResource(&uri)
ctx := context.Background()
declarationAttributes := fmt.Sprintf(`
name: %s
comment: %s
email: %s
keyringref: file://%s/keyring_%s.asc
`, name, comment, email, string(TempDir), name)
testKeyRing := keyRingDecl.Resource()
if e := testKeyRing.LoadString(declarationAttributes, codec.FormatYaml); e != nil {
log.Fatal(e)
}
testKeyRing.UseConfig(MockConfigValueGetter(func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}))
if _, err := testKeyRing.Read(ctx); err != nil {
log.Fatal(err)
}
testKeyRingResource := testKeyRing.(*OpenPGPKeyRing)
testKeyRingResource.Resources = folio.NewResourceMapper()
if testKeyRingResource.entityList[0].PrivateKey == nil {
log.Fatal("Keyring does not contain a private key")
}
/*
return TestRefMapper[*folio.Declaration](func(key string) (*folio.Declaration, bool) {
switch key {
case uri:
slog.Info("KEYRING", "name", name, "addr", testKeyRing.(*OpenPGPKeyRing).entityList[0].PrivateKey)
return keyRingDecl, true
}
return nil, false
}), folio.URI(uri)
*/
testKeyRingResource.Resources.Set(folio.URI(uri), keyRingDecl)
return testKeyRingResource.Resources, folio.URI(uri)
}
func DataTestKeyRing(keyRingPath string) (folio.ReferenceMapper[*folio.Declaration], folio.URI) {
keyData, err := os.ReadFile(keyRingPath)
if err != nil {
panic(err)
}
keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewReader(keyData))
if err != nil {
panic(err)
}
var name, comment, email string
for _, entity := range keyring {
for _, identity := range entity.Identities {
if identity.UserId != nil {
name = identity.UserId.Name
comment = identity.UserId.Comment
email = identity.UserId.Email
}
}
}
uri := fmt.Sprintf("openpgp-keyring://%s/%s/%s", name, comment, email)
keyRingDecl := folio.NewDeclaration()
keyRingDecl.NewResource(&uri)
ctx := context.Background()
declarationAttributes := fmt.Sprintf(`
name: %s
comment: %s
email: %s
keyringref: file://%s
`, name, comment, email, keyRingPath)
testKeyRing := keyRingDecl.Resource()
if e := testKeyRing.LoadString(declarationAttributes, codec.FormatYaml); e != nil {
log.Fatal(e)
}
testKeyRing.UseConfig(MockConfigValueGetter(func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}))
if _, err := testKeyRing.Read(ctx); err != nil {
log.Fatal(err)
}
testKeyRingResource := testKeyRing.(*OpenPGPKeyRing)
testKeyRingResource.Resources = folio.NewResourceMapper()
if testKeyRingResource.entityList[0].PrivateKey == nil {
log.Fatal("Keyring does not contain a private key")
}
testKeyRingResource.Resources.Set(folio.URI(uri), keyRingDecl)
return testKeyRingResource.Resources, folio.URI(uri)
}
func TestNewOpenPGPSignatureResource(t *testing.T) {
assert.NotNil(t, NewOpenPGPSignature())
}
func TestSigningEntity(t *testing.T) {
m, keyRingUri := NewTestUserKeys("TestUser5", "TestUser5", "testuser5@rosskeen.house")
assert.NotNil(t, m)
assert.Equal(t, folio.URI("openpgp-keyring://TestUser5/TestUser5/testuser5@rosskeen.house"), keyRingUri)
assert.Nil(t, TempDir.CreateFile("signing-test.txt", "test data"))
assert.FileExists(t, fmt.Sprintf("%s/keyring_TestUser5.asc", TempDir))
testUserKeyRingResource := folio.Dereference(keyRingUri, m)
assert.NotNil(t, testUserKeyRingResource)
assert.NotNil(t, testUserKeyRingResource.Resource().(*OpenPGPKeyRing).entityList[0].PrivateKey)
declarationAttributes := fmt.Sprintf(`
keyringref:
uri: %s
sourceref:
uri: file://%s/signing-test.txt
`, string(keyRingUri), string(TempDir))
testSignature := NewOpenPGPSignature()
e := testSignature.LoadString(declarationAttributes, codec.FormatYaml)
assert.Nil(t, e)
testSignature.Resources = m
testSignature.UseConfig(MockConfigValueGetter(func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}))
assert.False(t, testSignature.KeyRingRef.IsEmpty())
slog.Info("TestSigningEntity", "keyringref", testSignature.KeyRingRef, "resourcemap", testSignature.Resources)
keyRingResource := testSignature.KeyRingRef.Lookup(testSignature.Resources)
assert.NotNil(t, keyRingResource)
ringFileStream, streamErr := keyRingResource.ContentReaderStream()
assert.Nil(t, streamErr)
assert.NotNil(t, ringFileStream)
assert.Nil(t, testSignature.SigningEntity())
assert.NotNil(t, testSignature.entityList)
assert.Len(t, testSignature.entityList, 1)
assert.NotNil(t, testSignature.entityList[0].PrivateKey)
}
func TestSign(t *testing.T) {
//ctx := context.Background()
m, keyRingUri := NewTestUserKeys("TestUser2", "TestUser2", "testuser2@rosskeen.house")
assert.NotNil(t, m)
assert.Equal(t, folio.URI("openpgp-keyring://TestUser2/TestUser2/testuser2@rosskeen.house"), keyRingUri)
assert.Nil(t, TempDir.CreateFile("sign-test.txt", "test data"))
declarationAttributes := fmt.Sprintf(`
keyringref:
uri: %s
sourceref:
uri: file://%s/sign-test.txt
`, string(keyRingUri), string(TempDir))
testSignature := NewOpenPGPSignature()
testSignature.Resources = m
assert.Nil(t, testSignature.LoadString(declarationAttributes, codec.FormatYaml))
testSignature.UseConfig(MockConfigValueGetter(func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}))
assert.Nil(t, testSignature.SigningEntity())
sourceReadStream, err := testSignature.SourceRef.Lookup(testSignature.Resources).ContentReaderStream()
var signatureStream, armoredWriter io.WriteCloser
assert.True(t, testSignature.SignatureRef.IsEmpty())
var signatureContent bytes.Buffer
signatureStream = ext.WriteNopCloser(&signatureContent)
defer func() { testSignature.Signature = signatureContent.String() }()
if armoredWriter, err = armor.Encode(signatureStream, openpgp.SignatureType, nil); err != nil {
err = fmt.Errorf("%w: %w", ErrArmoredWriterFailed, err)
}
defer armoredWriter.Close()
slog.Info("TESTSIGN KEYRING", "name", "TestUser2", "addr", testSignature.KeyRingRef.Lookup(testSignature.Resources).(*OpenPGPKeyRing))
assert.Len(t, testSignature.entityList, 1)
slog.Info("Signing Entity", "entity", testSignature.entityList[0])
assert.NotNil(t, testSignature.entityList[0].PrivateKey)
assert.Nil(t, testSignature.Sign(sourceReadStream, armoredWriter))
}
func TestCreateSignature(t *testing.T) {
ctx := context.Background()
m, keyRingUri := NewTestUserKeys("TestUser3", "TestUser3", "testuser3@rosskeen.house")
assert.NotNil(t, m)
assert.Equal(t, folio.URI("openpgp-keyring://TestUser3/TestUser3/testuser3@rosskeen.house"), keyRingUri)
assert.Nil(t, TempDir.CreateFile("test3.txt", "test data\n"))
declarationAttributes := fmt.Sprintf(`
keyringref:
uri: %s
sourceref:
uri: file://%s/test3.txt
`, string(keyRingUri), string(TempDir))
testSignature := NewOpenPGPSignature()
testSignature.Resources = m
testSignature.UseConfig(MockConfigValueGetter(func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}))
e := testSignature.LoadString(declarationAttributes, codec.FormatYaml)
assert.Nil(t, e)
err := testSignature.Create(ctx)
assert.Nil(t, err)
assert.Greater(t, len(testSignature.entityList), 0)
assert.Contains(t, testSignature.entityList[0].Identities, "TestUser3 (TestUser3) <testuser3@rosskeen.house>")
assert.NotContains(t, testSignature.Signature, "-----END PGP PUBLIC KEY BLOCK-----")
assert.NotContains(t, testSignature.Signature, "-----END PGP PRIVATE KEY BLOCK-----")
assert.Contains(t, testSignature.Signature, "-----END PGP SIGNATURE-----")
}
func TestReadSignature(t *testing.T) {
ctx := context.Background()
assert.Nil(t, TempDir.CreateFile("read-test.txt", "test data\n"))
m, keyRingUri := KeyRingTestUser1()
assert.NotNil(t, m)
assert.Equal(t, folio.URI("openpgp-keyring://TestUser1/TestUser1/testuser@rosskeen.house"), keyRingUri)
declarationAttributes := fmt.Sprintf(`
keyringref:
uri: %s
sourceref:
uri: file://%s/read-test.txt
signature: |-
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEAM6cDwBqHcVfKX+b3weSNhbTZdcFAmhQtmMACgkQ3weSNhbT
ZddNPAf/ZSKVOUXVlIBgXMsw2RqVWYkOzyuWADeOq6P1UHlRN0xxSmOFnHukxstL
zTa7KSpf5y3/DKRSTWldAy8WYFr0mx5hoDy5c83OYZo2oUtFsVYifol4JfZeF+ij
6a2trW17VjtKYzwpSTt/SAaTxKj/6oVevpWykOPfg6V3CCLfnVEuBMhotU91ngbg
wh3R3K7LrVVJ6kYI4RKUeBIx280JZMG0sZ/AuwUdWG6KFavGMbHVzHHD2PMwT53t
xJ5kzWyS9ZWws8r/B33GM9szHplXulhETsd1S3x0/R2MoVcHeAaAa6JwD0y0Kxu6
MuQM3twP32lK4UUqNx4oPHzU5gbirA==
=+dVO
-----END PGP SIGNATURE-----
` , string(keyRingUri), string(TempDir))
testSignature := NewOpenPGPSignature()
testSignature.Resources = m
testSignature.UseConfig(MockConfigValueGetter(func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}))
e := testSignature.LoadDecl(declarationAttributes)
assert.Nil(t, e)
y, err := testSignature.Read(ctx)
assert.Nil(t, err)
assert.NotNil(t, y)
assert.Greater(t, len(testSignature.entityList), 0)
assert.Contains(t, testSignature.entityList[0].Identities, "TestUser1 (TestUser1) <testuser@rosskeen.house>")
}
func TestSignatureBlock(t *testing.T) {
assert.Nil(t, TempDir.CreateFile("block-test.txt", "test data\n"))
m, keyRingUri := KeyRingTestUser1()
assert.NotNil(t, m)
assert.Equal(t, folio.URI("openpgp-keyring://TestUser1/TestUser1/testuser@rosskeen.house"), keyRingUri)
declarationAttributes := fmt.Sprintf(`
keyringref:
uri: %s
sourceref:
uri: file://%s/block-test.txt
signature: |-
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEAM6cDwBqHcVfKX+b3weSNhbTZdcFAmhQtmMACgkQ3weSNhbT
ZddNPAf/ZSKVOUXVlIBgXMsw2RqVWYkOzyuWADeOq6P1UHlRN0xxSmOFnHukxstL
zTa7KSpf5y3/DKRSTWldAy8WYFr0mx5hoDy5c83OYZo2oUtFsVYifol4JfZeF+ij
6a2trW17VjtKYzwpSTt/SAaTxKj/6oVevpWykOPfg6V3CCLfnVEuBMhotU91ngbg
wh3R3K7LrVVJ6kYI4RKUeBIx280JZMG0sZ/AuwUdWG6KFavGMbHVzHHD2PMwT53t
xJ5kzWyS9ZWws8r/B33GM9szHplXulhETsd1S3x0/R2MoVcHeAaAa6JwD0y0Kxu6
MuQM3twP32lK4UUqNx4oPHzU5gbirA==
=+dVO
-----END PGP SIGNATURE-----
` , string(keyRingUri), string(TempDir))
testSignature := NewOpenPGPSignature()
testSignature.Resources = m
testSignature.UseConfig(MockConfigValueGetter(func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}))
e := testSignature.LoadDecl(declarationAttributes)
assert.Nil(t, e)
err := testSignature.DecodeSignatureBlock()
assert.Nil(t, err)
}
func TestVerifySignature(t *testing.T) {
ctx := context.Background()
assert.Nil(t, TempDir.CreateFile("verify-test.txt", "test data\n"))
m, keyRingUri := KeyRingTestUser1()
assert.NotNil(t, m)
assert.Equal(t, folio.URI("openpgp-keyring://TestUser1/TestUser1/testuser@rosskeen.house"), keyRingUri)
declarationAttributes := fmt.Sprintf(`
keyringref:
uri: %s
sourceref:
uri: file://%s/verify-test.txt
signature: |-
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEAM6cDwBqHcVfKX+b3weSNhbTZdcFAmhQtmMACgkQ3weSNhbT
ZddNPAf/ZSKVOUXVlIBgXMsw2RqVWYkOzyuWADeOq6P1UHlRN0xxSmOFnHukxstL
zTa7KSpf5y3/DKRSTWldAy8WYFr0mx5hoDy5c83OYZo2oUtFsVYifol4JfZeF+ij
6a2trW17VjtKYzwpSTt/SAaTxKj/6oVevpWykOPfg6V3CCLfnVEuBMhotU91ngbg
wh3R3K7LrVVJ6kYI4RKUeBIx280JZMG0sZ/AuwUdWG6KFavGMbHVzHHD2PMwT53t
xJ5kzWyS9ZWws8r/B33GM9szHplXulhETsd1S3x0/R2MoVcHeAaAa6JwD0y0Kxu6
MuQM3twP32lK4UUqNx4oPHzU5gbirA==
=+dVO
-----END PGP SIGNATURE-----
` , string(keyRingUri), string(TempDir))
testSignature := NewOpenPGPSignature()
testSignature.Resources = m
testSignature.UseConfig(MockConfigValueGetter(func(key string) (any, error) {
switch key {
case "passphrase":
return "foo", nil
}
return nil, fmt.Errorf("%w: %s", data.ErrUnknownConfigurationKey, key)
}))
e := testSignature.LoadDecl(declarationAttributes)
assert.Nil(t, e)
y, err := testSignature.Read(ctx)
assert.Nil(t, err)
assert.NotNil(t, y)
assert.Greater(t, len(testSignature.entityList), 0)
assert.Contains(t, testSignature.entityList[0].Identities, "TestUser1 (TestUser1) <testuser@rosskeen.house>")
assert.Equal(t, "DF07923616D365D7", fmt.Sprintf("%X", testSignature.entityList[0].PrimaryKey.KeyId))
sourceReadStream, sourceReadStreamErr := testSignature.SourceRef.ContentReaderStream()
assert.Nil(t, sourceReadStreamErr)
assert.Nil(t, testSignature.DecodeSignatureBlock())
assert.Nil(t, testSignature.Verify(sourceReadStream))
sourceReadStream.Close()
assert.Nil(t, testSignature.DecodeSignatureBlock())
sourceReadStream2, sourceReadStreamErr2 := testSignature.SourceRef.ContentReaderStream()
assert.Nil(t, sourceReadStreamErr2)
assert.Nil(t, testSignature.Verify(sourceReadStream2))
}
func TestVerifyDocumentSignature(t *testing.T) {
ctx := context.Background()
assert.Nil(t, TempDir.CreateFile("verify-test.txt", "test data\n"))
m, keyRingUri := DataKeyRing("file://../../tests/data/openpgp-keyring/keyring_jx.yaml")
assert.NotNil(t, m)
assert.Equal(t, folio.URI("openpgp-keyring://TestUser1/TestUser1/testuser@rosskeen.house"), keyRingUri)
// load a document
docURI := folio.URI("file://../../examples/signed/ubuntu-dev-read.jx.yaml")
r, readerErr := docURI.ContentReaderStream()
assert.Nil(t, readerErr)
assert.NotNil(t, r)
doc := folio.DocumentRegistry.NewDocument(docURI)
assert.Nil(t, doc.LoadReader(r, codec.FormatYaml))
declarationAttributes := fmt.Sprintf(`
keyringref:
uri: %s
sourceref:
uri: %s
type: document
` , string(keyRingUri), string(docURI))
testSignature := NewOpenPGPSignature()
testSignature.Resources = m
testSignature.UseConfig(mockKeyRingPassphraseConfig)
e := testSignature.LoadDecl(declarationAttributes)
assert.Nil(t, e)
createErr := testSignature.Create(ctx)
assert.Nil(t, createErr)
assert.Greater(t, len(testSignature.entityList), 0)
assert.Contains(t, testSignature.entityList[0].Identities, "TestUser1 (TestUser1) <testuser@rosskeen.house>")
y, err := testSignature.Read(ctx) // XXX throws an error if no signature is present
assert.Nil(t, err)
assert.NotNil(t, y)
assert.Greater(t, len(testSignature.entityList), 0)
assert.Contains(t, testSignature.entityList[0].Identities, "TestUser1 (TestUser1) <testuser@rosskeen.house>")
assert.Equal(t, "FAED7F3BB05EF687", fmt.Sprintf("%X", testSignature.entityList[0].PrimaryKey.KeyId))
sourceReadStream, sourceReadStreamErr := testSignature.SourceRef.Reader()
assert.Nil(t, sourceReadStreamErr)
assert.Nil(t, testSignature.DecodeSignatureBlock())
assert.Nil(t, testSignature.Verify(sourceReadStream))
sourceReadStream.Close()
assert.Nil(t, testSignature.DecodeSignatureBlock())
sourceReadStream2, sourceReadStreamErr2 := testSignature.SourceRef.Reader()
assert.Nil(t, sourceReadStreamErr2)
assert.Nil(t, testSignature.Verify(sourceReadStream2))
}