// 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() }
// NewToken returns a blinded token ready for signing. Blindmessage goes to server, blindfactors and clear message remain local func (c Client) NewToken(issuerPubKey *signkeys.PublicKey, pubParams *jjm.BlindingParamClient, owner *[ed25519.PublicKeySize]byte) (genericblinding.BlindingFactors, genericblinding.BlindMessage, *token.Token, error) { newToken := token.New(&issuerPubKey.KeyID, owner) if newToken == nil { return nil, nil, nil, ErrNoToken } blindClient := jjm.NewGenericBlindingClient(&issuerPubKey.PublicKey, c.Curve) clearMessage := jjm.NewClearMessage(newToken.Hash()) blindingParams := jjm.NewBlindingParamClient(&issuerPubKey.PublicKey) blindingParams.PointRs1 = pubParams.PointRs1 blindingParams.PointRs2 = pubParams.PointRs2 blindingParams.ScalarLs1 = pubParams.ScalarLs1 blindingParams.ScalarLs2 = pubParams.ScalarLs2 blindFactors, blindMessage, err := blindClient.Blind(blindingParams, clearMessage) if err != nil { return nil, nil, nil, err } return blindMessage, blindFactors, newToken, err }
// 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 }