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