Skip to content

Commit

Permalink
Merge branch 'master' into docker-push-image
Browse files Browse the repository at this point in the history
  • Loading branch information
ivard authored Aug 8, 2023
2 parents 2e0ef5c + 94740c6 commit 979864f
Show file tree
Hide file tree
Showing 41 changed files with 240 additions and 211 deletions.
4 changes: 2 additions & 2 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ runs:
using: composite
steps:
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: ^1.16
go-version: ^1.18

- name: Determine artifact output filename
id: artifact-name-generator
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/status-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ jobs:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: ^1.16
go-version: ^1.18

- name: Run gofmt
# gofmt does not return non-zero exit codes on failure, so we have to check that there are no issues using grep.
Expand All @@ -75,6 +75,12 @@ jobs:
- name: Run misspell
run: misspell -error .

- name: Install staticcheck
run: go install honnef.co/go/tools/cmd/[email protected]

- name: Run staticcheck
run: staticcheck -checks "all,-ST1000,-ST1003,-SA1019,-SA1029" ./...

test:
runs-on: ubuntu-latest
timeout-minutes: 10
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Validate revocation witness before revocation update is applied
- RevocationStorage's EnableRevocation function does not return an error anymore if it has been enabled already
- Use a scratch Docker image as base for the Dockerfile
- Custom WrapErrorPrefix function that respects the error's type
- Log info message of irma.SessionError errors

As part of e-mail address revalidation:
- `VerifyMXRecord` incorporates a check to see if there is an active network connection
Expand All @@ -33,6 +35,16 @@ As part of e-mail address revalidation:
### Removed
- Superfluous openssl package in Dockerfile

### Security
- Let IRMA servers by default reject IRMA/Yivi apps that don't support pairing codes (IRMA protocol version <= 2.7)

**Note:** This is an important security update for issuers to make sure that pairing codes cannot be circumvented.
IRMA apps that don't support pairing codes should not be in circulation anymore, so this change won't affect users.
Yivi apps have always supported pairing codes.

### Internal
- Linter switch from golint to staticcheck

## [0.12.6] - 2023-05-31
### Fixed
- Legacy endpoints of keyshare server return 403 status codes when database is down
Expand Down
32 changes: 26 additions & 6 deletions attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ var (
credentialID = metadataField{16, 8}
)

// metadataField contains the length and offset of a field within a metadata attribute.
// MetadataField contains the length and offset of a field within a metadata attribute.
type metadataField struct {
length int
offset int
}

// metadataAttribute represents a metadata attribute. Contains the credential type, signing date, validity, and the public key counter.
// MetadataAttribute represents a metadata attribute. Contains the credential type, signing date, validity, and the public key counter.
type MetadataAttribute struct {
Int *big.Int
pk *gabikeys.PublicKey
Expand All @@ -59,16 +59,16 @@ type AttributeList struct {
func NewAttributeListFromInts(ints []*big.Int, conf *Configuration) *AttributeList {
metadata := MetadataFromInt(ints[0], conf)
credtype := metadata.CredentialType()
idx := credtype.RevocationIndex + 1
var rev bool
revocationSupported := false
if credtype != nil {
rev = credtype.RevocationSupported() &&
idx := credtype.RevocationIndex + 1
revocationSupported = credtype.RevocationSupported() &&
len(ints) > idx && ints[idx] != nil && ints[idx].Cmp(bigZero) != 0
}
return &AttributeList{
Ints: ints,
MetadataAttribute: metadata,
RevocationSupported: rev,
RevocationSupported: revocationSupported,
}
}

Expand Down Expand Up @@ -217,6 +217,26 @@ func (al *AttributeList) Attribute(identifier AttributeTypeIdentifier) Translate
return nil
}

func (al *AttributeList) CredentialInfo() *CredentialInfo {
credtype := al.CredentialType()
if credtype == nil {
return nil
}
id := credtype.Identifier()
issid := id.IssuerIdentifier()
return &CredentialInfo{
ID: id.Name(),
IssuerID: issid.Name(),
SchemeManagerID: issid.SchemeManagerIdentifier().Name(),
SignedOn: Timestamp(al.SigningDate()),
Expires: Timestamp(al.Expiry()),
Attributes: al.Map(),
Hash: al.Hash(),
Revoked: al.Revoked,
RevocationSupported: al.RevocationSupported,
}
}

// MetadataFromInt wraps the given Int
func MetadataFromInt(i *big.Int, conf *Configuration) *MetadataAttribute {
return &MetadataAttribute{Int: i, Conf: conf}
Expand Down
22 changes: 1 addition & 21 deletions credinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,11 @@ type CredentialInfo struct {
// A CredentialInfoList is a list of credentials (implements sort.Interface).
type CredentialInfoList []*CredentialInfo

func (attrs *AttributeList) CredentialInfo() *CredentialInfo {
credtype := attrs.CredentialType()
if credtype == nil {
return nil
}
id := credtype.Identifier()
issid := id.IssuerIdentifier()
return &CredentialInfo{
ID: id.Name(),
IssuerID: issid.Name(),
SchemeManagerID: issid.SchemeManagerIdentifier().Name(),
SignedOn: Timestamp(attrs.SigningDate()),
Expires: Timestamp(attrs.Expiry()),
Attributes: attrs.Map(),
Hash: attrs.Hash(),
Revoked: attrs.Revoked,
RevocationSupported: attrs.RevocationSupported,
}
}

func (ci CredentialInfo) GetCredentialType(conf *Configuration) *CredentialType {
return conf.CredentialTypes[ci.Identifier()]
}

// Returns true if credential is expired at moment of calling this function
// IsExpired returns true if credential is expired at moment of calling this function
func (ci CredentialInfo) IsExpired() bool {
return ci.Expires.Before(Timestamp(time.Now()))
}
Expand Down
4 changes: 2 additions & 2 deletions descriptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ type AttributeType struct {
Name TranslatedString
Description TranslatedString

RandomBlind bool `xml:"randomblind,attr,optional" json:",omitempty"`
RandomBlind bool `xml:"randomblind,attr,omitempty" json:",omitempty"`

Index int `xml:"-"`
DisplayIndex *int `xml:"displayIndex,attr" json:",omitempty"`
Expand Down Expand Up @@ -621,7 +621,7 @@ func (ad AttributeType) IsOptional() bool {
return ad.Optional == "true"
}

// Returns indices of random blind attributes within this credentialtype
// RandomBlindAttributeIndices returns indices of random blind attributes within this credentialtype
// The indices coincide with indices of an AttributeList (metadataAttribute at index 0)
func (ct *CredentialType) RandomBlindAttributeIndices() []int {
indices := []int{}
Expand Down
4 changes: 2 additions & 2 deletions identifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ func (oi metaObjectIdentifier) Root() string {
}
}

func (io metaObjectIdentifier) PartsCount() int {
return strings.Count(string(io), ".")
func (oi metaObjectIdentifier) PartsCount() int {
return strings.Count(string(oi), ".")
}

// NewRequestorSchemeIdentifier converts the specified identifier to a RequestorSchemeIdentifier.
Expand Down
4 changes: 2 additions & 2 deletions internal/keysharecore/usersecrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ func (s *unencryptedUserSecrets) setID(id []byte) error {
return nil
}

func (user *unencryptedUserSecrets) verifyPin(pin string) error {
func (s *unencryptedUserSecrets) verifyPin(pin string) error {
paddedPin, err := padBytes([]byte(pin), 64)
if err != nil {
return err
}
if subtle.ConstantTimeCompare(user.Pin, paddedPin) != 1 {
if subtle.ConstantTimeCompare(s.Pin, paddedPin) != 1 {
return ErrInvalidPin
}
return nil
Expand Down
6 changes: 5 additions & 1 deletion internal/sessiontest/legacy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

irma "github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/test"
"github.com/privacybydesign/irmago/server/irmaserver"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -37,13 +38,16 @@ func testSessionUsingLegacyStorage(t *testing.T, dir string) {

// Re-open client
require.NoError(t, client.Close())
client, handler = parseExistingStorage(t, handler.storage)
client, _ = parseExistingStorage(t, handler.storage)

// Test whether credential is still there after the storage has been reloaded
doSession(t, getDisclosureRequest(idRoot), client, nil, nil, nil, nil)
}

func TestWithoutPairingSupport(t *testing.T) {
irmaserver.AcceptInsecureProtocolVersions = true
defer func() { irmaserver.AcceptInsecureProtocolVersions = false }()

t.Run("SigningSession", apply(testSigningSession, nil, optionPrePairingClient))
t.Run("DisclosureSession", apply(testDisclosureSession, nil, optionPrePairingClient))
t.Run("NoAttributeDisclosureSession", apply(testNoAttributeDisclosureSession, nil, optionPrePairingClient))
Expand Down
2 changes: 1 addition & 1 deletion internal/sessiontest/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func TestLogging(t *testing.T) {

// Check whether log entry for signature session is actually stored
require.NoError(t, client.Close())
client, handler = parseExistingStorage(t, handler.storage)
client, _ = parseExistingStorage(t, handler.storage)
logs, err = client.LoadNewestLogs(100)
require.NoError(t, err)
require.True(t, len(logs) == oldLogLength+3)
Expand Down
5 changes: 3 additions & 2 deletions internal/sessiontest/redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,9 @@ func TestRedisUpdates(t *testing.T) {

var o interface{}
transport := irma.NewHTTPTransport(qr.URL, false)
transport.SetHeader(irma.MinVersionHeader, "2.5")
transport.SetHeader(irma.MaxVersionHeader, "2.5")
transport.SetHeader(irma.MinVersionHeader, "2.8")
transport.SetHeader(irma.MaxVersionHeader, "2.8")
transport.SetHeader(irma.AuthorizationHeader, "testauthtoken")
clientToken, err := mr.Get("token:" + string(token))
require.NoError(t, err)

Expand Down
36 changes: 30 additions & 6 deletions internal/sessiontest/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func testIssuanceSameAttributesNotSingleton(t *testing.T, conf interface{}, opts

// Also check whether this is actually stored
require.NoError(t, client.Close())
client, handler = parseExistingStorage(t, handler.storage)
client, _ = parseExistingStorage(t, handler.storage)
require.Equal(t, prevLen+1, len(client.CredentialInfoList()))
}

Expand Down Expand Up @@ -272,7 +272,7 @@ func testIssuanceSingletonCredential(t *testing.T, conf interface{}, opts ...opt

// Also check whether this is actually stored
require.NoError(t, client.Close())
client, handler = parseExistingStorage(t, handler.storage)
client, _ = parseExistingStorage(t, handler.storage)
require.NotNil(t, client.Attributes(credid, 0))
require.Nil(t, client.Attributes(credid, 1))
}
Expand Down Expand Up @@ -447,7 +447,7 @@ func testIssuedCredentialIsStored(t *testing.T, conf interface{}, opts ...option
doSession(t, issuanceRequest, client, nil, nil, nil, conf, opts...)
require.NoError(t, client.Close())

client, handler = parseExistingStorage(t, handler.storage)
client, _ = parseExistingStorage(t, handler.storage)
id := irma.NewAttributeTypeIdentifier("irma-demo.MijnOverheid.fullName.familyname")
doSession(t, getDisclosureRequest(id), client, nil, nil, nil, conf, opts...)
}
Expand Down Expand Up @@ -962,7 +962,7 @@ func TestPOSTSizeLimit(t *testing.T) {
req, err := http.NewRequest(
http.MethodPost,
requestorServerURL+"/session/",
bytes.NewReader(make([]byte, server.PostSizeLimit+1, server.PostSizeLimit+1)),
bytes.NewReader(make([]byte, server.PostSizeLimit+1)),
)
require.NoError(t, err)
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
Expand Down Expand Up @@ -1091,12 +1091,36 @@ func TestDoubleGET(t *testing.T) {
// Simulate the first GET by the client in the session protocol, twice
var o interface{}
transport := irma.NewHTTPTransport(qr.URL, false)
transport.SetHeader(irma.MinVersionHeader, "2.5")
transport.SetHeader(irma.MaxVersionHeader, "2.5")
transport.SetHeader(irma.MinVersionHeader, "2.8")
transport.SetHeader(irma.MaxVersionHeader, "2.8")
transport.SetHeader(irma.AuthorizationHeader, "testauthtoken")
require.NoError(t, transport.Get("", &o))
require.NoError(t, transport.Get("", &o))
}

func TestInsecureProtocolVersion(t *testing.T) {
irmaServer := StartIrmaServer(t, nil)
defer irmaServer.Stop()

// Test whether the server accepts a request with an insecure protocol version
request := irma.NewDisclosureRequest(irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID"))

qr, _, _, err := irmaServer.irma.StartSession(request, func(result *server.SessionResult) {})
require.NoError(t, err)

var o interface{}
transport := irma.NewHTTPTransport(qr.URL, false)
transport.SetHeader(irma.MinVersionHeader, "2.7")
transport.SetHeader(irma.MaxVersionHeader, "2.7")
transport.SetHeader(irma.AuthorizationHeader, "testauthtoken")
err = transport.Get("", &o)
require.Error(t, err)
serr, ok := err.(*irma.SessionError)
require.True(t, ok)
require.Equal(t, server.ErrorProtocolVersion.Status, serr.RemoteStatus)
require.Equal(t, string(server.ErrorProtocolVersion.Type), serr.RemoteError.ErrorName)
}

func TestClientDeveloperMode(t *testing.T) {
common.ForceHTTPS = true
defer func() { common.ForceHTTPS = false }()
Expand Down
2 changes: 1 addition & 1 deletion irma/cmd/genkeypair.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ var genkeypairCmd = &cobra.Command{
// Now generate the key pair
sysParams, ok := gabikeys.DefaultSystemParameters[keylength]
if !ok {
return fmt.Errorf("Unsupported key length, should be one of %v", gabikeys.DefaultKeyLengths)
return fmt.Errorf("unsupported key length, should be one of %v", gabikeys.DefaultKeyLengths)
}
privk, pubk, err := gabikeys.GenerateKeyPair(sysParams, numAttributes, counter, expiryDate)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion irma/cmd/issuer-keyprove.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ may be used.`,
}()

// Build the proof
bases := append([]*big.Int{pk.Z, pk.S})
bases := []*big.Int{pk.Z, pk.S}
if pk.G != nil {
bases = append(bases, pk.G)
}
Expand Down
2 changes: 1 addition & 1 deletion irma/cmd/issuer-keyverify.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ On machines of 2 - 3 GHz verification will take some 5 - 15 minutes, during whic
follower.StepDone()

// Construct proof structure
bases := append([]*big.Int{pk.Z, pk.S})
bases := []*big.Int{pk.Z, pk.S}
if pk.G != nil {
bases = append(bases, pk.G)
}
Expand Down
1 change: 0 additions & 1 deletion irma/cmd/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,6 @@ func authmethodAlias(f *pflag.FlagSet, name string) pflag.NormalizedName {
switch name {
case "authmethod":
name = "auth-method"
break
}
return pflag.NormalizedName(name)
}
Expand Down
2 changes: 1 addition & 1 deletion irma/cmd/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func skipSigning(path string, info os.FileInfo, typ irma.SchemeType) bool {
}
if !strings.HasSuffix(path, ".xml") &&
!strings.HasSuffix(path, ".png") &&
!regexp.MustCompile("kss-\\d+\\.pem$").Match([]byte(filepath.Base(path))) &&
!regexp.MustCompile(`kss-\d+\.pem$`).Match([]byte(filepath.Base(path))) &&
filepath.Base(path) != "timestamp" {
return true
}
Expand Down
Loading

0 comments on commit 979864f

Please sign in to comment.