@@ -95,6 +95,8 @@ var cnUtil = function(currencyConfig) {
95
95
} ;
96
96
97
97
var Z = "0000000000000000000000000000000000000000000000000000000000000000" ; //zero scalar
98
+ this . Z = Z ;
99
+
98
100
//H2 object to speed up some operations
99
101
var H2 = [
100
102
"8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94" ,
@@ -1364,7 +1366,7 @@ var cnUtil = function(currencyConfig) {
1364
1366
}
1365
1367
const eeComputed = this . array_hash_to_scalar ( Lv1 ) ;
1366
1368
const equalKeys = eeComputed === bb . ee ;
1367
- console . log ( `Keys equal? ${ equalKeys }
1369
+ console . log ( `[verifyBorromean] Keys equal? ${ equalKeys }
1368
1370
${ eeComputed }
1369
1371
${ bb . ee } ` ) ;
1370
1372
@@ -1444,6 +1446,41 @@ var cnUtil = function(currencyConfig) {
1444
1446
return sig ;
1445
1447
} ;
1446
1448
1449
+ //proveRange and verRange
1450
+ //proveRange gives C, and mask such that \sumCi = C
1451
+ // c.f. http://eprint.iacr.org/2015/1098 section 5.1
1452
+ // and Ci is a commitment to either 0 or 2^i, i=0,...,63
1453
+ // thus this proves that "amount" is in [0, 2^64]
1454
+ // mask is a such that C = aG + bH, and b = amount
1455
+ //verRange verifies that \sum Ci = C and that each Ci is a commitment to 0 or 2^i
1456
+
1457
+ this . verRange = function ( C , as , nrings = 64 ) {
1458
+ try {
1459
+ let CiH = [ ] ; // len 64
1460
+ let asCi = [ ] ; // len 64
1461
+ let Ctmp ;
1462
+ for ( let i = 0 ; i < nrings ; i ++ ) {
1463
+ CiH [ i ] = this . ge_sub ( as . Ci [ i ] , this . H2 [ i ] ) ;
1464
+ Ctmp = this . ge_add ( Ctmp , as . Ci [ i ] ) ;
1465
+ }
1466
+ const equalKeys = Ctmp === C ;
1467
+ console . log ( `[verRange] Equal keys? ${ equalKeys }
1468
+ C: ${ c }
1469
+ Ctmp: $${ Ctmp } ` ) ;
1470
+ if ( ! equalKeys ) {
1471
+ return false ;
1472
+ }
1473
+
1474
+ if ( ! this . verifyBorromean ( as . asig , asCi , CiH ) ) {
1475
+ return false ;
1476
+ }
1477
+
1478
+ return true ;
1479
+ } catch ( e ) {
1480
+ return false ;
1481
+ }
1482
+ } ;
1483
+
1447
1484
function array_hash_to_scalar ( array ) {
1448
1485
var buf = "" ;
1449
1486
for ( var i = 0 ; i < array . length ; i ++ ) {
@@ -1597,7 +1634,14 @@ var cnUtil = function(currencyConfig) {
1597
1634
return c ;
1598
1635
} ;
1599
1636
1600
- //prepares for MLSAG_Gen
1637
+ //Ring-ct MG sigs
1638
+ //Prove:
1639
+ // c.f. http://eprint.iacr.org/2015/1098 section 4. definition 10.
1640
+ // This does the MG sig on the "dest" part of the given key matrix, and
1641
+ // the last row is the sum of input commitments from that column - sum output commitments
1642
+ // this shows that sum inputs = sum outputs
1643
+ //Ver:
1644
+ // verifies the above sig is created corretly
1601
1645
this . proveRctMG = function ( message , pubs , inSk , kimg , mask , Cout , index ) {
1602
1646
var cols = pubs . length ;
1603
1647
if ( cols < 3 ) {
@@ -1616,6 +1660,64 @@ var cnUtil = function(currencyConfig) {
1616
1660
return this . MLSAG_Gen ( message , PK , xx , kimg , index ) ;
1617
1661
} ;
1618
1662
1663
+ //Ring-ct MG sigs
1664
+ //Prove:
1665
+ // c.f. http://eprint.iacr.org/2015/1098 section 4. definition 10.
1666
+ // This does the MG sig on the "dest" part of the given key matrix, and
1667
+ // the last row is the sum of input commitments from that column - sum output commitments
1668
+ // this shows that sum inputs = sum outputs
1669
+ //Ver:
1670
+ // verifies the above sig is created corretly
1671
+ // simple version, assuming only post Rct
1672
+ this . verRctMG = function ( mg , pubs , outPk , txnFeeKey , message , kimg ) {
1673
+ const cols = pubs . length ;
1674
+ if ( cols < 1 ) {
1675
+ throw Error ( "Empty pubs" ) ;
1676
+ }
1677
+ const rows = pubs [ 0 ] . length ;
1678
+ if ( rows < 1 ) {
1679
+ throw Error ( "Empty pubs" ) ;
1680
+ }
1681
+ for ( let i = 0 ; i < cols . length ; ++ i ) {
1682
+ if ( pubs [ i ] . length !== rows ) {
1683
+ throw Error ( "Pubs is not rectangular" ) ;
1684
+ }
1685
+ }
1686
+ // key vector of rows + 1 len
1687
+ const tmp = [ ] ;
1688
+ for ( let i = 0 ; i < rows + 1 ; i ++ ) {
1689
+ tmp [ i ] = this . identity ( ) ;
1690
+ }
1691
+
1692
+ // key matrix of (cols, tmp)
1693
+ let M = [ ] ;
1694
+
1695
+ //create the matrix to mg sig
1696
+ for ( let j = 0 ; j < rows ; j ++ ) {
1697
+ for ( let i = 0 ; i < cols ; i ++ ) {
1698
+ // add dimension
1699
+ M [ i ] . push ( [ ] ) ;
1700
+ M [ i ] [ j ] = pubs [ i ] [ j ] . dest ;
1701
+ M [ i ] [ rows ] = this . ge_add ( M [ i ] [ rows ] , outPk [ j ] . C ) ; //add Ci in last row
1702
+ }
1703
+ }
1704
+
1705
+ for ( let i = 0 ; i < cols ; i ++ ) {
1706
+ for ( let j = 0 ; j < outPk . length ; j ++ ) {
1707
+ M [ i ] [ rows ] = this . ge_sub ( M [ i ] [ rows ] , outPk [ J ] . C ) ; //subtract output Ci's in last row
1708
+ }
1709
+
1710
+ //subtract txn fee output in last row
1711
+ M [ i ] [ rows ] = this . ge_sub ( M [ i ] [ rows ] , txnFeeKey ) ;
1712
+ }
1713
+
1714
+ return this . MLSAG_ver ( message , M , mg , kimg ) ;
1715
+ } ;
1716
+
1717
+ this . verBulletProof = function ( ) {
1718
+ throw Error ( "verBulletProof is not implemented" ) ;
1719
+ } ;
1720
+
1619
1721
this . get_pre_mlsag_hash = function ( rv ) {
1620
1722
var hashes = "" ;
1621
1723
hashes += rv . message ;
@@ -1768,6 +1870,77 @@ var cnUtil = function(currencyConfig) {
1768
1870
return rv ;
1769
1871
} ;
1770
1872
1873
+ this . verRct = function ( rv , semantics ) {
1874
+ if ( rv . type === 0x03 ) {
1875
+ throw Error ( "Bulletproof validation not implemented" ) ;
1876
+ }
1877
+
1878
+ // where RCTTypeFull is 0x01 and RCTTypeFullBulletproof is 0x03
1879
+ if ( rv . type !== 0x01 && rv . type !== 0x03 ) {
1880
+ throw Error ( "verRct called on non-full rctSig" ) ;
1881
+ }
1882
+ if ( semantics ) {
1883
+ //RCTTypeFullBulletproof checks not implemented
1884
+ // RCTTypeFull checks
1885
+ if ( rv . outPk . length !== rv . p . rangeSigs . length ) {
1886
+ throw Error ( "Mismatched sizes of outPk and rv.p.rangeSigs" ) ;
1887
+ }
1888
+ if ( rv . outPk . length !== rv . ecdhInfo . length ) {
1889
+ throw Error ( "Mismatched sizes of outPk and rv.ecdhInfo" ) ;
1890
+ }
1891
+ if ( rv . p . MGs . length !== 1 ) {
1892
+ throw Error ( "full rctSig has not one MG" ) ;
1893
+ }
1894
+ } else {
1895
+ // semantics check is early, we don't have the MGs resolved yet
1896
+ }
1897
+ try {
1898
+ if ( semantics ) {
1899
+ const results = [ ] ;
1900
+ for ( let i = 0 ; i < rv . outPk . length ; i ++ ) {
1901
+ // might want to parallelize this like its done in the c++ codebase
1902
+ // via some abstraction library to support browser + node
1903
+ if ( rv . p . rangeSigs . length === 0 ) {
1904
+ results [ i ] = verBulletproof ( rv . p . bulletproofs [ i ] ) ;
1905
+ } else {
1906
+ // mask -> C if public
1907
+ results [ i ] = verRange ( rv . outPk [ i ] . C , rv . p . rangeSigs [ i ] ) ;
1908
+ }
1909
+ }
1910
+
1911
+ for ( let i = 0 ; i < rv . outPk . length ; i ++ ) {
1912
+ if ( ! results [ i ] ) {
1913
+ console . error (
1914
+ "Range proof verification failed for output" ,
1915
+ i ,
1916
+ ) ;
1917
+ return false ;
1918
+ }
1919
+ }
1920
+ } else {
1921
+ // compute txn fee
1922
+ const txnFeeKey = this . ge_scalarmult ( H , this . d2s ( rv . txnFee ) ) ;
1923
+ const mgVerd = verRctMg (
1924
+ rv . p . MGs [ 0 ] ,
1925
+ rv . mixRing ,
1926
+ rv . outPk ,
1927
+ txnFeeKey ,
1928
+ this . get_pre_mlsag_hash ( rv ) ,
1929
+ ) ;
1930
+ console . log ( "mg sig verified?" , mgVerd ) ;
1931
+ if ( ! mgVerd ) {
1932
+ console . error ( "MG Signature verification failed" ) ;
1933
+ return false ;
1934
+ }
1935
+ }
1936
+ } catch ( e ) {
1937
+ console . error ( "Error in vetRCt: " , e ) ;
1938
+ }
1939
+ } ;
1940
+
1941
+ this . verBulletProof = function ( ) {
1942
+ throw Error ( "verBulletProof is not implemented" ) ;
1943
+ } ;
1771
1944
//end RCT functions
1772
1945
1773
1946
this . add_pub_key_to_extra = function ( extra , pubkey ) {
0 commit comments