Пример #1
0
// Unblind a signature and convert it into a token
func (c Client) Unblind(storeLocal *types.ReissuePacketPrivate, signature []byte) ([]byte, error) {
	pubkey, err := new(signkeys.PublicKey).Unmarshal(storeLocal.PublicKey)
	if err != nil {
		return nil, err
	}
	params, err := jjm.NewBlindingFactors(&pubkey.PublicKey).Unmarshal(storeLocal.Factors)
	if err != nil {
		return nil, err
	}
	token, err := token.Unmarshal(storeLocal.Token)
	if err != nil {
		return nil, err
	}
	clearMessage := jjm.NewClearMessage(token.Hash())
	blindSig, err := jjm.NewBlindSignature(&pubkey.PublicKey).Unmarshal(signature)
	blindClient := jjm.NewGenericBlindingClient(&pubkey.PublicKey, c.Curve)
	sig, _, err := blindClient.Unblind(params, clearMessage, blindSig)
	if err != nil {
		return nil, err
	}
	_, err = blindClient.Verify(sig, clearMessage)
	if err != nil {
		return nil, err
	}
	t := sig.(jjm.ClearSignature)
	token.AddSignature(&t)
	return token.Marshal()
}
Пример #2
0
// Verify a given inputToken and return it's public key if it verifies.
func (c *Client) Verify(inputToken []byte) (outputToken *TokenEntry, err error) {
	tokenUnmarshalled, err := token.Unmarshal(inputToken)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	keyid, owner := tokenUnmarshalled.Properties()
	pubkey, err := c.getPubKey(*keyid)
	if err != nil {
		return nil, err
	}
	// Check if it is expired. Duplicate. Keypool does that as well
	if pubkey.Expire < times.Now() {
		c.LastError = ErrExpireToken
		return nil, ErrFinal
	}
	// Get data from token, signature first
	signature := tokenUnmarshalled.GetSignature()
	tempSignature := jjm.NewClearSignature(&pubkey.PublicKey)
	tempSignature.PointR = signature.PointR
	tempSignature.ScalarS = signature.ScalarS
	tempSignature.ScalarR = signature.ScalarR
	// Get signature message
	clearMessage := jjm.NewClearMessage(tokenUnmarshalled.Hash())
	// Verify the signature
	blindClient := jjm.NewGenericBlindingClient(&pubkey.PublicKey, c.packetClient.Curve)
	ok, err := blindClient.Verify(tempSignature, clearMessage)
	if err != nil || !ok {
		c.LastError = err
		return nil, ErrFinal
	}
	outputToken = &TokenEntry{
		Hash:        tokenUnmarshalled.Hash(),
		Token:       inputToken,
		OwnerPubKey: owner,
		Usage:       pubkey.Usage,
		Expire:      pubkey.Expire,
	}
	return outputToken, nil
}
Пример #3
0
// WalletToken gets a token from wallet that matches usage.
// The token is reissued for owner if not nil.
// If the token is a subscription-token and owner is not present, it
// is stored and a "NeedReissue" error is returned.
func (c *Client) WalletToken(usage string, owner *[ed25519.PublicKeySize]byte) (tokenHash []byte, err error) {
	newToken, params, pubkeyUsed, err := c.getTokenFromWallet(usage)
	if err != nil {
		return nil, err
	}
	// Cache token, params
	tokenUnmarshalled, err := token.Unmarshal(newToken)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	// Parse pubkeyUsed and add to keypool
	signerPubKey, err := new(signkeys.PublicKey).Unmarshal(pubkeyUsed)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	keyid, err := c.packetClient.Keypool.LoadKey(signerPubKey)
	if err != nil && err != keypool.ErrExists {
		c.LastError = err
		return nil, ErrFatal
	}
	c.packetClient.Keypool.SaveKey(*keyid)
	// If we have params this is not renewable
	renewable := false
	if params == nil || len(params) == 0 {
		renewable = true
	} else {
		// Unless the params state otherwise....
		_, _, _, canReissue, err := types.UnmarshalParams(params)
		if err != nil {
			c.LastError = err
			return nil, ErrFatal
		}
		if canReissue {
			renewable = true
		}
	}
	//tokenUnmarshalled.KeyID
	ownerPubkey, ownerPrivkey := splitKey(c.walletKey)
	// Set tokenentry struct for storage
	tokenentry := TokenEntry{
		Hash:         tokenUnmarshalled.Hash(),
		Token:        newToken,
		Params:       params,
		OwnerPubKey:  ownerPubkey,
		OwnerPrivKey: ownerPrivkey,
		Renewable:    renewable,
		CanReissue:   true,
		Usage:        signerPubKey.Usage,
		Expire:       signerPubKey.Expire,
	}
	err = c.walletStore.SetToken(tokenentry) // Cache current state
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	if owner == nil && renewable == false {
		return tokenentry.Hash, ErrNeedReissue
	}
	// Reissue
	return c.ReissueToken(tokenentry.Hash, owner)
}
Пример #4
0
// Reissue creates a request to be sent to the server to reissue a new token for an old token. oldOwner is the Private key for whoever owned oldToken.
// NewOwner is the public key for whoever is to own the new token. Both can be nil.
func (c Client) Reissue(oldTokenEnc []byte, oldOwner *[ed25519.PrivateKeySize]byte, newOwner *[ed25519.PublicKeySize]byte, params []byte) (toServer []byte, storeLocal *types.ReissuePacketPrivate, err error) {
	packet := new(types.ReissuePacket)
	packet.CallType = types.CallTypeReissue
	oldToken, err := token.Unmarshal(oldTokenEnc)
	if err != nil {
		return nil, nil, err
	}
	// Get info from parameters
	pubKey, pubParams, _, canReissue, err := types.UnmarshalParams(params)
	if err != nil {
		return nil, nil, err
	}
	// Verify that oldToken and params match
	oldKeyID := new([signkeys.KeyIDSize]byte)
	copy(oldKeyID[:], oldToken.KeyID)
	oldPubKey, err := c.Keypool.Lookup(*oldKeyID)
	if err != nil {
		return nil, nil, err
	}
	// Verify usage
	if oldPubKey.Usage != pubKey.Usage {
		return nil, nil, ErrParamMismatch
	}
	// Verify same service-guard
	if oldPubKey.Signer != pubKey.Signer {
		return nil, nil, ErrParamMismatch
	}
	// Add parameter publickey to keypool
	saveID, err := c.Keypool.LoadKey(pubKey)
	if err != nil && err != keypool.ErrExists {
		return nil, nil, err
	}
	// Save key to permanent storage
	if err == nil {
		c.Keypool.SaveKey(*saveID)
	}
	// Create new token data
	blindMessage, blindFactors, newToken, err := c.NewToken(pubKey, pubParams, newOwner)
	if err != nil {
		return nil, nil, err
	}
	packet.Token, err = oldToken.Marshal()
	if err != nil {
		return nil, nil, err
	}
	packet.BlindToken, err = blindMessage.Marshal()
	if err != nil {
		return nil, nil, err
	}
	packet.Params = params
	_, owner := oldToken.Properties()
	if owner != nil {
		if oldOwner == nil {
			return nil, nil, ErrMissingSigner
		}
	}
	packet.Sign(oldOwner)
	rpacket, err := packet.Marshal()
	if err != nil {
		return nil, nil, err
	}
	local := new(types.ReissuePacketPrivate)
	local.CanReissue = canReissue
	local.PublicKey, err = pubKey.Marshal()
	if err != nil {
		return nil, nil, err
	}
	local.Factors, err = blindFactors.Marshal()
	if err != nil {
		return nil, nil, err
	}
	local.Token, err = newToken.Marshal()
	if err != nil {
		return nil, nil, err
	}
	rhash := packet.Hash()
	local.RequestHash = rhash[:]
	local.Request = rpacket

	return rpacket, local, nil
}
Пример #5
0
// ReissueToken reissues a token identified by tokenHash for owner.
func (c *Client) ReissueToken(tokenHash []byte, ownerPubkey *[ed25519.PublicKeySize]byte) (newTokenHash []byte, err error) {
	var ownerPrivkey *[ed25519.PrivateKeySize]byte
	if !c.IsOnline() {
		c.LastError = ErrOffline
		return nil, ErrOffline
	}
	onlineGroup.Add(1)
	defer onlineGroup.Done()
	// Lock token against other use
	lockID := c.LockToken(tokenHash)
	if lockID == 0 {
		c.LastError = ErrLocked
		return nil, ErrRetry
	}
	defer c.UnlockToken(tokenHash)
	// Get client and token data
	issueClient, err := guardrpc.New(c.cacert)
	if err != nil {
		c.LastError = err
		return nil, ErrRetry
	}
	tokenEntry, err := c.walletStore.GetToken(tokenHash, lockID)
	if err != nil {
		c.LastError = err
		if err == ErrLocked {
			return nil, ErrRetry
		}
		return nil, ErrFatal
	}
	if tokenEntry.OwnerPrivKey == nil {
		c.LastError = ErrNotMine
		return nil, ErrFatal
	}
	tokenUnmarshalled, err := token.Unmarshal(tokenEntry.Token)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	keyid, _ := tokenUnmarshalled.Properties()
	key, err := c.packetClient.Keypool.Lookup(*keyid)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	// Test if we are communicating already
	if tokenEntry.ServerPacket == nil {
		// Test if we have params
		if tokenEntry.Params == nil {
			params, err := issueClient.GetParams(&key.Signer)
			if err != nil {
				c.LastError = err
				_, fatal, err := lookupError(err)
				if fatal {
					c.LastError = err
					return nil, ErrFinal
				}
				return nil, ErrRetry
			}
			tokenEntry.Params = params
			err = c.walletStore.SetToken(*tokenEntry)
			if err != nil {
				c.LastError = err
				return nil, ErrFatal
			}
		}
		// Generate new owner if no owner is specified
		if ownerPubkey == nil {
			ownerPubkey, ownerPrivkey, err = ed25519.GenerateKey(rand.Reader)
			if err != nil {
				c.LastError = err
				return nil, ErrFatal
			}
			tokenEntry.NewOwnerPrivKey = ownerPrivkey
		}
		tokenEntry.NewOwnerPubKey = ownerPubkey
		// Generate blinding packet
		serverPacket, blindingFactors, err := c.packetClient.Reissue(tokenEntry.Token, tokenEntry.OwnerPrivKey, tokenEntry.NewOwnerPubKey, tokenEntry.Params)
		if err != nil {
			c.LastError = err
			return nil, ErrFatal
		}
		// Marshall local, store packet and local in walletStore
		tokenEntry.BlindingFactors, err = blindingFactors.Marshal()
		if err != nil {
			c.LastError = err
			return nil, ErrFatal
		}
		tokenEntry.ServerPacket = serverPacket
		err = c.walletStore.SetToken(*tokenEntry)
		if err != nil {
			c.LastError = err
			return nil, ErrFatal
		}
	}
	// We have everything, make the call
	replyPacket, newPubkey, err := issueClient.Reissue(&key.Signer, tokenEntry.ServerPacket)
	if err != nil {
		c.LastError = err
		_, fatal, err := lookupError(err)
		if fatal {
			c.LastError = err
			return nil, ErrFinal
		}
		return nil, ErrRetry
	}
	c.walletStore.DelToken(tokenEntry.Hash) // Delete old token, it's invalid from here
	// Parse new pubkey and add to keypool
	signerPubKey, err := new(signkeys.PublicKey).Unmarshal(newPubkey)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	keyid, err = c.packetClient.Keypool.LoadKey(signerPubKey)
	if err != nil && err != keypool.ErrExists {
		c.LastError = err
		return nil, ErrFatal
	}
	c.packetClient.Keypool.SaveKey(*keyid)
	// Unblind the new token
	blindingFactors, err := new(types.ReissuePacketPrivate).Unmarshal(tokenEntry.BlindingFactors)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	newToken, err := c.packetClient.Unblind(blindingFactors, replyPacket)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	// Write it to database
	tokenUnmarshalled, err = token.Unmarshal(newToken)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	keyid, _ = tokenUnmarshalled.Properties()
	signerPubKey, err = c.packetClient.Keypool.Lookup(*keyid)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	tokenentryNew := TokenEntry{
		Hash:         tokenUnmarshalled.Hash(),
		Token:        newToken,
		Params:       nil,
		OwnerPubKey:  tokenEntry.NewOwnerPubKey,
		OwnerPrivKey: tokenEntry.NewOwnerPrivKey,
		Renewable:    tokenEntry.Renewable,
		CanReissue:   tokenEntry.Renewable,
		Usage:        signerPubKey.Usage,
		Expire:       signerPubKey.Expire,
	}
	err = c.walletStore.SetToken(tokenentryNew)
	if err != nil {
		c.LastError = err
		return nil, ErrFatal
	}
	return tokenentryNew.Hash, nil
}