Penetration Test Report (NCCGroup): NCC Group Zcash NU3 Blossom Report 2020 02 06 v1.1

NU3 Specification and Blossom
Implementation Audit
Zcash
February 6, 2020 – Version 1.1
Preparedfor
TaylorHornby
BenjaminWinston
Preparedby
GéraldDoussot
ThomasPornin
©2020–NCCGroup
PreparedbyNCCGroupSecurityServices,Inc. forZcash. Portionsofthisdocumentandthetemplates
usedinitsproductionarethepropertyofNCCGroupandcannotbecopied(infullorinpart)without
NCCGroup’spermission.
Whileprecautionshavebeentakeninthepreparationofthisdocument,NCCGroupthepublisher,and
theauthor(s)assumenoresponsibilityforerrors,omissions,orfordamagesresultingfromtheuseof
the information contained herein. Use of NCC Group’s services does not guarantee the security of a
system,orthatcomputerintrusionswillnotoccur.
Executive Summary
Synopsis nobalancegoesnegative. Thisdependencymechanism
In October 2019, the Electric Coin Company engaged justifies the removal of the coinbase maturity rule for
NCC Group to conduct a review of two Zcash im- shieldedoutputs.
provement proposals (ZIP 213 and ZIP 221) and of
In ZIP 221, two issues were found in the pseudocode
the implementation of ZIP 208 within the Zcash node
fortheoperationsonthehashtree;theyaredescribed
implementation. ZIP 213 proposes a change to
in finding NCC-1908_Zcash-001 on page 5 and find-
consensusrulestoallowcoinbasetransactionstotarget
ingNCC-1908_Zcash-002onpage6. Theseissueslead
shielded addresses. ZIP 221 describes a novel type
towrongcomputationsthatmightgounnoticedduring
of hash trees meant to support efficient validation of
development, since all implementations following that
transactionsbylightweightclients. Theimplementation
pseudocode would behave identically to each other,
of ZIP 208 applies a change of target pacing for block
but would still exclude some block headers from the
issuance,sothatoverallnetworklatencyishalved. Two
hash tree. A number of smaller issues and remarks
consultantsperformedtheengagementforatotalof15
were assembled in Appendix B on page 12; most of
person-days.
theseareconcerningconsistencyofthedescriptionor
typography, and NCC Group deemed them unlikely to
Scope
leadtoanyvulnerabilityinfutureimplementations.
NCCGroup’sevaluationincluded:
In PR 4025, no serious issues were uncovered. A very
• TheZIP213draft,asofcommit90ad18f.1
minor imperfection in the validation of a command-
• TheZIP221draft,asofcommitb6be377.2
line parameter was detected, and is described in find-
• The implementation of ZIP 208, as made in pull
ing NCC-1908_Zcash-003 on page 8; it has no real
request 4025.3 PR 4025 was merged into the main
consequenceonsecurity.
ZcashtreeonAugust9,2019;thescopecoveredthat
setofcommits,lastofwhichwasb99003conAugust
StrategicRecommendations
7.
Since ZIP 221 pseudocode follows a Python syntax,
NCC Group recommends converting that pseudocode
Limitations
intorunnablePythoncode,sothatextensiveunittests
ZIP213and221,beingdraftspecifications,donothave
can be made, in particular with respect to edge cases
corresponding implementations. Therefore, analysis
(addingoneorseveralnodestoanemptytree,removing
of potential security issues was based on how such
allnodesfromatree,removinganexactfullsubtree,and
implementationscouldplausiblybebuilt. Inparticular,
soon).
theassessmentoftheseverityofthetwoissuesfound
in the pseudocode of ZIP 221 was based on the
estimatedlikelihoodthattheywouldresultinflawsinthe
implementationthatmayfailtobedetectedbybasicunit
testing. Any specific future implementation may have
differentcharacteristics.
KeyFindings
In ZIP 213, no issues were found. The description
of the change appears to be fully correct and in
line with its purported goals and rationale. Notably,
the analysis found in the draft regarding coinbase
transaction maturity clearly explains how anchors in
shielded transactions act as an enforced dependency
system on whole sequences of transactions, contrary
totransparenttransactionsthataremorefree-standing
and can be inserted in blocks in any order as long as
1https://github.com/str4d/zips/blob/90ad18ff228e86830da965a5180cfc6e2acac520/zip-0213.rst
2https://github.com/therealyingtong/zips/blob/b6be3770c9cbd340b57d6dd6786d43ddf0610189/zip-0221.rst
3https://github.com/zcash/zcash/pull/4025
2 | ZcashNU3SpecificationandBlossomImplementationAudit
Dashboard
TargetMetadata EngagementData
Name ZcashProtocolandImplementation Type SpecificationandImplementation
Review
Method Code-assisted
Dates 2019-10-21to2019-10-31
Consultants 2
LevelofEffort 15person-days
FindingBreakdown
Criticalissues 0
Highissues 2
Mediumissues 0
Lowissues 0
Informationalissues 1
Totalissues 3
CategoryBreakdown
Cryptography 2
DataValidation 1
ComponentBreakdown
ZIP208implementation 1
ZIP221 2
Key
Critical High Medium Low Informational
3 | ZcashNU3SpecificationandBlossomImplementationAudit
Table of Findings
Foreachfinding,NCCGroupusesacompositeriskscorethattakesintoaccounttheseverityoftherisk,application’s
exposureanduserpopulation,technicaldifficultyofexploitation,andotherfactors. ForanexplanationofNCCGroup’s
riskratingandfindingcategorization,seeAppendixAonpage10.
Title ID Risk
MissingLastProcessedPeakinappend() 001 High
WrongListofPeaksReturnedbyget_peaks() 002 High
UncheckedPossibleTruncation 003 Informational
4 | ZcashNU3SpecificationandBlossomImplementationAudit
Finding Details
Finding MissingLastProcessedPeakinappend()
Risk High Impact: High,Exploitability: Undetermined
Identifier NCC-1908_Zcash-001
Category Cryptography
Component ZIP221
Location Functionappend()intheZIP221pseudocode.
Impact The specification may lead to an incorrect implementation of ZIP 221 where the computed
MMR tree is incomplete, i.e. missing block header information. Simplified Payment Veri-
fication (SPV) clients use this information to validate the blockchain and the inclusion of a
transactioninablock. Ifthisinformationisincomplete,clientscannotdetermineaccurately
whatamountofcurrencytheyownandcanspend.
Description TheZIP221specificationdocumentsmodificationstotheZcashblockheaderformattoin-
cludeMerkleMountainRange(MMR)commitments. Thespecificationincludespseudocode
forthealgorithmofseveralroutinestomanipulatetheMMRtreedatastructure. Specifically,
theappend()functionpermitstomergealeafnodetoanexistingMMRtree.
Theappend()functionusesthecurrentvariabletooperateiterativelyinalooponthepeak
being processed. Its content will be used in the next iteration of the loop. When the loop
exits,thecontentofcurrentisnotaddedtothelistofpeakstobebaggedinbag_peaks(),
thereforetheresultingMMRtreewillmissthisfinalpeak.
Theissueisillustratedinthecodesnippetbelow:
def append(root: ZcashMMRNode, leaf: ZcashMMRNode) -> ZcashMMRNode:
'''Append a leaf to an existing tree, return the new tree root'''
# recursively find a list of peaks in the current tree
peaks: List[ZcashMMRNode] = get_peaks(root)
merged: List[ZcashMMRNode] = []
# Merge peaks from right to left.
# This will produce a list of peaks in reverse order
current = leaf
for peak in peaks[::-1]:
current_leaves = current.latest_height - current.earliest_height + 1
peak_leaves = peak.latest_height - peak.earliest_height + 1
if current_leaves == peak_leaves:
current = make_parent(peak, current)
else:
merged.append(current)
current = peak
# finally, bag the merged peaks
return bag_peaks(merged[::-1])
Recommendation Ensure that all peaks are bagged. This can be achieved by adding the following statement
beforethelaststatementoftheappend()function:
merged.append(current)
5 | ZcashNU3SpecificationandBlossomImplementationAudit
Finding WrongListofPeaksReturnedbyget_peaks()
Risk High Impact: High,Exploitability: Undetermined
Identifier NCC-1908_Zcash-002
Category Cryptography
Component ZIP221
Location Functionget_peaks()inZIP221pseudocode.
Impact The get_peaks() function may return the wrong list of peaks, leading to a wrong MMR
computation that could omit some block headers. If this information is incomplete, clients
cannotdetermineaccuratelywhatamountofcurrencytheyownandcanspend.
Description Theget_peaks()functiontakesasinputtherootfortheMMR,andextractsthepeaks. Itis
thereverseoperationofthebag_pe