Merge branch 'develop' into jsonrpc
This commit is contained in:
		
						commit
						7a894e3738
					
				| @ -46,7 +46,7 @@ Go Ethereum comes with several binaries found in | ||||
| * `mist` Official Ethereum Browser | ||||
| * `ethereum` Ethereum CLI | ||||
| * `ethtest` test tool which runs with the [tests](https://github.com/ethereum/testes) suit:  | ||||
|   `ethtest "`cat myfile.json`"`. | ||||
|   `cat file | ethtest`. | ||||
| * `evm` is a generic Ethereum Virtual Machine: `evm -code 60ff60ff -gas | ||||
|   10000 -price 0 -dump`. See `-h` for a detailed description. | ||||
| 
 | ||||
|  | ||||
| @ -9,15 +9,16 @@ import Ethereum 1.0 | ||||
| 
 | ||||
| Rectangle { | ||||
| 	id: window | ||||
|     objectName: "browserView" | ||||
|     anchors.fill: parent | ||||
|     color: "#00000000" | ||||
| 	anchors.fill: parent | ||||
| 	color: "#00000000" | ||||
| 
 | ||||
| 	property var title: "Browser" | ||||
| 	property var title: "DApps" | ||||
| 	property var iconSource: "../browser.png" | ||||
| 	property var menuItem | ||||
|     property var hideUrl: true | ||||
| 
 | ||||
| 	property alias url: webview.url | ||||
|     property alias windowTitle: webview.title | ||||
| 	property alias webView: webview | ||||
| 
 | ||||
| 	property var cleanPath: false | ||||
| @ -66,8 +67,7 @@ Rectangle { | ||||
| 		webview.url = "http://etherian.io" | ||||
| 	} | ||||
| 
 | ||||
| 	signal messages(var messages, int id); | ||||
| 	onMessages: { | ||||
|     function messages(messages, id) { | ||||
| 		// Bit of a cheat to get proper JSON | ||||
| 		var m = JSON.parse(JSON.parse(JSON.stringify(messages))) | ||||
| 		webview.postEvent("eth_changed", id, m); | ||||
| @ -139,315 +139,310 @@ Rectangle { | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|         // Border | ||||
|         Rectangle { | ||||
|             id: divider | ||||
|             anchors { | ||||
|                 left: parent.left | ||||
|                 right: parent.right | ||||
|                 top: navBar.bottom | ||||
|             } | ||||
|             z: -1 | ||||
|             height: 1 | ||||
|             color: "#CCCCCC" | ||||
|         } | ||||
| 		// Border | ||||
| 		Rectangle { | ||||
| 			id: divider | ||||
| 			anchors { | ||||
| 				left: parent.left | ||||
| 				right: parent.right | ||||
| 				top: navBar.bottom | ||||
| 			} | ||||
| 			z: -1 | ||||
| 			height: 1 | ||||
| 			color: "#CCCCCC" | ||||
| 		} | ||||
| 
 | ||||
| 		WebView { | ||||
| 			objectName: "webView" | ||||
| 			id: webview | ||||
| 		ScrollView { | ||||
| 			anchors { | ||||
| 				left: parent.left | ||||
| 				right: parent.right | ||||
| 				bottom: parent.bottom | ||||
| 				top: divider.bottom | ||||
| 			} | ||||
| 
 | ||||
| 			function injectJs(js) { | ||||
| 				webview.experimental.navigatorQtObjectEnabled = true; | ||||
| 				webview.experimental.evaluateJavaScript(js) | ||||
| 				webview.experimental.javascriptEnabled = true; | ||||
| 			} | ||||
| 
 | ||||
| 			function sendMessage(data) { | ||||
| 				webview.experimental.postMessage(JSON.stringify(data)) | ||||
| 			} | ||||
| 
 | ||||
| 
 | ||||
| 			experimental.preferences.javascriptEnabled: true | ||||
| 			experimental.preferences.webGLEnabled: true | ||||
| 			experimental.itemSelector:  MouseArea { | ||||
| 				// To avoid conflicting with ListView.model when inside Initiator context. | ||||
| 				property QtObject selectorModel: model | ||||
| 			WebView { | ||||
| 				objectName: "webView" | ||||
| 				id: webview | ||||
| 				anchors.fill: parent | ||||
| 				onClicked: selectorModel.reject() | ||||
| 
 | ||||
| 				Menu { | ||||
| 					visible: true | ||||
| 					id: itemSelector | ||||
| 				function sendMessage(data) { | ||||
| 					webview.experimental.postMessage(JSON.stringify(data)) | ||||
| 				} | ||||
| 
 | ||||
| 					Instantiator { | ||||
| 						model: selectorModel.items | ||||
| 						delegate: MenuItem { | ||||
| 							text: model.text | ||||
| 							onTriggered: { | ||||
| 								selectorModel.accept(index) | ||||
| 				experimental.preferences.javascriptEnabled: true | ||||
| 				experimental.preferences.webAudioEnabled: true | ||||
| 				experimental.preferences.pluginsEnabled: true | ||||
| 				experimental.preferences.navigatorQtObjectEnabled: true | ||||
| 				experimental.preferences.developerExtrasEnabled: true | ||||
| 				experimental.preferences.webGLEnabled: true | ||||
| 				experimental.preferences.notificationsEnabled: true | ||||
| 				experimental.preferences.localStorageEnabled: true | ||||
| 				experimental.userAgent:"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36  (KHTML, like Gecko) Mist/0.1 Safari/537.36" | ||||
| 
 | ||||
| 				experimental.itemSelector:  MouseArea { | ||||
| 					// To avoid conflicting with ListView.model when inside Initiator context. | ||||
| 					property QtObject selectorModel: model | ||||
| 					anchors.fill: parent | ||||
| 					onClicked: selectorModel.reject() | ||||
| 
 | ||||
| 					Menu { | ||||
| 						visible: true | ||||
| 						id: itemSelector | ||||
| 
 | ||||
| 						Instantiator { | ||||
| 							model: selectorModel.items | ||||
| 							delegate: MenuItem { | ||||
| 								text: model.text | ||||
| 								onTriggered: { | ||||
| 									selectorModel.accept(index) | ||||
| 								} | ||||
| 							} | ||||
| 							onObjectAdded: itemSelector.insertItem(index, object) | ||||
| 							onObjectRemoved: itemSelector.removeItem(object) | ||||
| 						} | ||||
| 						onObjectAdded: itemSelector.insertItem(index, object) | ||||
| 						onObjectRemoved: itemSelector.removeItem(object) | ||||
| 					} | ||||
| 
 | ||||
| 					Component.onCompleted: { | ||||
| 						itemSelector.popup() | ||||
| 					} | ||||
| 				} | ||||
| 				experimental.userScripts: ["../ext/q.js", "../ext/ethereum.js/lib/web3.js", "../ext/ethereum.js/lib/qt.js", "../ext/setup.js"] | ||||
| 				experimental.onMessageReceived: { | ||||
| 					//console.log("[onMessageReceived]: ", message.data) | ||||
| 					var data = JSON.parse(message.data) | ||||
| 
 | ||||
| 					try { | ||||
| 						switch(data.call) { | ||||
| 							case "eth_compile": | ||||
| 							postData(data._id, eth.compile(data.args[0])) | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_coinbase": | ||||
| 							postData(data._id, eth.coinBase()) | ||||
| 
 | ||||
| 							case "eth_account": | ||||
| 							postData(data._id, eth.key().address); | ||||
| 
 | ||||
| 							case "eth_istening": | ||||
| 							postData(data._id, eth.isListening()) | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_mining": | ||||
| 							postData(data._id, eth.isMining()) | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_peerCount": | ||||
| 							postData(data._id, eth.peerCount()) | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_countAt": | ||||
| 							require(1) | ||||
| 							postData(data._id, eth.txCountAt(data.args[0])) | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_codeAt": | ||||
| 							require(1) | ||||
| 							var code = eth.codeAt(data.args[0]) | ||||
| 							postData(data._id, code); | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_blockByNumber": | ||||
| 							require(1) | ||||
| 							var block = eth.blockByNumber(data.args[0]) | ||||
| 							postData(data._id, block) | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_blockByHash": | ||||
| 							require(1) | ||||
| 							var block = eth.blockByHash(data.args[0]) | ||||
| 							postData(data._id, block) | ||||
| 							break | ||||
| 
 | ||||
| 							require(2) | ||||
| 							var block = eth.blockByHash(data.args[0]) | ||||
| 							postData(data._id, block.transactions[data.args[1]]) | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_transactionByHash": | ||||
| 							case "eth_transactionByNumber": | ||||
| 							require(2) | ||||
| 
 | ||||
| 							var block; | ||||
| 							if (data.call === "transactionByHash") | ||||
| 							block = eth.blockByHash(data.args[0]) | ||||
| 							else | ||||
| 							block = eth.blockByNumber(data.args[0]) | ||||
| 
 | ||||
| 							var tx = block.transactions.get(data.args[1]) | ||||
| 
 | ||||
| 							postData(data._id, tx) | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_uncleByHash": | ||||
| 							case "eth_uncleByNumber": | ||||
| 							require(2) | ||||
| 
 | ||||
| 							var block; | ||||
| 							if (data.call === "uncleByHash") | ||||
| 							block = eth.blockByHash(data.args[0]) | ||||
| 							else | ||||
| 							block = eth.blockByNumber(data.args[0]) | ||||
| 
 | ||||
| 							var uncle = block.uncles.get(data.args[1]) | ||||
| 
 | ||||
| 							postData(data._id, uncle) | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "transact": | ||||
| 							require(5) | ||||
| 
 | ||||
| 							var tx = eth.transact(data.args) | ||||
| 							postData(data._id, tx) | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_stateAt": | ||||
| 							require(2); | ||||
| 
 | ||||
| 							var storage = eth.storageAt(data.args[0], data.args[1]); | ||||
| 							postData(data._id, storage) | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_call": | ||||
| 							require(1); | ||||
| 							var ret = eth.call(data.args) | ||||
| 							postData(data._id, ret) | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_balanceAt": | ||||
| 							require(1); | ||||
| 
 | ||||
| 							postData(data._id, eth.balanceAt(data.args[0])); | ||||
| 							break | ||||
| 
 | ||||
| 							case "eth_watch": | ||||
| 							require(2) | ||||
| 							eth.watch(data.args[0], data.args[1]) | ||||
| 
 | ||||
| 							case "eth_disconnect": | ||||
| 							require(1) | ||||
| 							postData(data._id, null) | ||||
| 							break; | ||||
| 
 | ||||
| 							case "eth_newFilterString": | ||||
| 							require(1) | ||||
| 							var id = eth.newFilterString(data.args[0], window) | ||||
| 							postData(data._id, id); | ||||
| 							break; | ||||
| 
 | ||||
| 							case "eth_newFilter": | ||||
| 							require(1) | ||||
| 							var id = eth.newFilter(data.args[0], window) | ||||
| 
 | ||||
| 							postData(data._id, id); | ||||
| 							break; | ||||
| 
 | ||||
| 							case "eth_filterLogs": | ||||
| 							require(1); | ||||
| 
 | ||||
| 							var messages = eth.messages(data.args[0]); | ||||
| 							var m = JSON.parse(JSON.parse(JSON.stringify(messages))) | ||||
| 							postData(data._id, m); | ||||
| 
 | ||||
| 							break; | ||||
| 
 | ||||
| 							case "eth_deleteFilter": | ||||
| 							require(1); | ||||
| 							eth.uninstallFilter(data.args[0]) | ||||
| 							break; | ||||
| 
 | ||||
| 
 | ||||
| 							case "shh_newFilter": | ||||
| 							require(1); | ||||
| 							var id = shh.watch(data.args[0], window); | ||||
| 							postData(data._id, id); | ||||
| 							break; | ||||
| 
 | ||||
| 							case "shh_newIdentity": | ||||
| 							var id = shh.newIdentity() | ||||
| 							postData(data._id, id) | ||||
| 
 | ||||
| 							break | ||||
| 
 | ||||
| 							case "shh_post": | ||||
| 							require(1); | ||||
| 
 | ||||
| 							var params = data.args[0]; | ||||
| 							var fields = ["payload", "to", "from"]; | ||||
| 							for(var i = 0; i < fields.length; i++) { | ||||
| 								params[fields[i]] = params[fields[i]] || ""; | ||||
| 							} | ||||
| 							if(typeof params.payload !== "object") { params.payload = [params.payload]; } //params.payload = params.payload.join(""); } | ||||
| 							params.topics = params.topics || []; | ||||
| 							params.priority = params.priority || 1000; | ||||
| 							params.ttl = params.ttl || 100; | ||||
| 
 | ||||
| 							shh.post(params.payload, params.to, params.from, params.topics, params.priority, params.ttl); | ||||
| 
 | ||||
| 							break; | ||||
| 
 | ||||
| 							case "shh_getMessages": | ||||
| 							require(1); | ||||
| 
 | ||||
| 							var m = shh.messages(data.args[0]); | ||||
| 							var messages = JSON.parse(JSON.parse(JSON.stringify(m))); | ||||
| 							postData(data._id, messages); | ||||
| 
 | ||||
| 							break; | ||||
| 
 | ||||
| 							case "ssh_newGroup": | ||||
| 							postData(data._id, ""); | ||||
| 							break; | ||||
| 						} | ||||
| 					} catch(e) { | ||||
| 						console.log(data.call + ": " + e) | ||||
| 
 | ||||
| 						postData(data._id, null); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				Component.onCompleted: { | ||||
| 					itemSelector.popup() | ||||
| 				function post(seed, data) { | ||||
| 					postData(data._id, data) | ||||
| 				} | ||||
| 			} | ||||
| 			experimental.preferences.webAudioEnabled: true | ||||
| 			experimental.preferences.navigatorQtObjectEnabled: true | ||||
| 			experimental.preferences.developerExtrasEnabled: true | ||||
| 			experimental.userScripts: ["../ext/q.js", "../ext/ethereum.js/lib/web3.js", "../ext/ethereum.js/lib/qt.js", "../ext/setup.js"] | ||||
| 			experimental.onMessageReceived: { | ||||
| 				console.log("[onMessageReceived]: ", message.data) | ||||
| 				// TODO move to messaging.js | ||||
| 				var data = JSON.parse(message.data) | ||||
| 
 | ||||
| 				try { | ||||
| 					switch(data.call) { | ||||
| 						case "eth_compile": | ||||
| 						postData(data._id, eth.compile(data.args[0])) | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_coinbase": | ||||
| 						postData(data._id, eth.coinBase()) | ||||
| 
 | ||||
| 						case "eth_account": | ||||
| 						postData(data._id, eth.key().address); | ||||
| 
 | ||||
| 						case "eth_istening": | ||||
| 						postData(data._id, eth.isListening()) | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_mining": | ||||
| 						postData(data._id, eth.isMining()) | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_peerCount": | ||||
| 						postData(data._id, eth.peerCount()) | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_countAt": | ||||
| 						require(1) | ||||
| 						postData(data._id, eth.txCountAt(data.args[0])) | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_codeAt": | ||||
| 						require(1) | ||||
| 						var code = eth.codeAt(data.args[0]) | ||||
| 						postData(data._id, code); | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_blockByNumber": | ||||
| 						require(1) | ||||
| 						var block = eth.blockByNumber(data.args[0]) | ||||
| 						postData(data._id, block) | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_blockByHash": | ||||
| 						require(1) | ||||
| 						var block = eth.blockByHash(data.args[0]) | ||||
| 						postData(data._id, block) | ||||
| 						break | ||||
| 
 | ||||
| 						require(2) | ||||
| 						var block = eth.blockByHash(data.args[0]) | ||||
| 						postData(data._id, block.transactions[data.args[1]]) | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_transactionByHash": | ||||
| 						case "eth_transactionByNumber": | ||||
| 						require(2) | ||||
| 
 | ||||
| 						var block; | ||||
| 						if (data.call === "transactionByHash") | ||||
| 						block = eth.blockByHash(data.args[0]) | ||||
| 						else | ||||
| 						block = eth.blockByNumber(data.args[0]) | ||||
| 
 | ||||
| 						var tx = block.transactions.get(data.args[1]) | ||||
| 
 | ||||
| 						postData(data._id, tx) | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_uncleByHash": | ||||
| 						case "eth_uncleByNumber": | ||||
| 						require(2) | ||||
| 
 | ||||
| 						var block; | ||||
| 						if (data.call === "uncleByHash") | ||||
| 						block = eth.blockByHash(data.args[0]) | ||||
| 						else | ||||
| 						block = eth.blockByNumber(data.args[0]) | ||||
| 
 | ||||
| 						var uncle = block.uncles.get(data.args[1]) | ||||
| 
 | ||||
| 						postData(data._id, uncle) | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "transact": | ||||
| 						require(5) | ||||
| 
 | ||||
| 						var tx = eth.transact(data.args) | ||||
| 						postData(data._id, tx) | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_stateAt": | ||||
| 						require(2); | ||||
| 
 | ||||
| 						var storage = eth.storageAt(data.args[0], data.args[1]); | ||||
| 						postData(data._id, storage) | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_call": | ||||
| 						require(1); | ||||
| 						var ret = eth.call(data.args) | ||||
| 						postData(data._id, ret) | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_balanceAt": | ||||
| 						require(1); | ||||
| 
 | ||||
| 						postData(data._id, eth.balanceAt(data.args[0])); | ||||
| 						break | ||||
| 
 | ||||
| 						case "eth_watch": | ||||
| 						require(2) | ||||
| 						eth.watch(data.args[0], data.args[1]) | ||||
| 
 | ||||
| 						case "eth_disconnect": | ||||
| 						require(1) | ||||
| 						postData(data._id, null) | ||||
| 						break; | ||||
| 
 | ||||
| 						case "eth_newFilterString": | ||||
| 						require(1) | ||||
| 						var id = eth.newFilterString(data.args[0]) | ||||
| 						postData(data._id, id); | ||||
| 						break; | ||||
| 
 | ||||
| 						case "eth_newFilter": | ||||
| 						require(1) | ||||
| 						var id = eth.newFilter(data.args[0]) | ||||
| 
 | ||||
| 						postData(data._id, id); | ||||
| 						break; | ||||
| 
 | ||||
| 						case "eth_filterLogs": | ||||
| 						require(1); | ||||
| 
 | ||||
| 						var messages = eth.messages(data.args[0]); | ||||
| 						var m = JSON.parse(JSON.parse(JSON.stringify(messages))) | ||||
| 						postData(data._id, m); | ||||
| 
 | ||||
| 						break; | ||||
| 
 | ||||
| 						case "eth_deleteFilter": | ||||
| 						require(1); | ||||
| 						eth.uninstallFilter(data.args[0]) | ||||
| 						break; | ||||
| 
 | ||||
| 
 | ||||
| 						case "shh_newFilter": | ||||
| 						require(1); | ||||
| 						var id = shh.watch(data.args[0], window); | ||||
| 						postData(data._id, id); | ||||
| 						break; | ||||
| 
 | ||||
| 						case "shh_newIdentity": | ||||
| 						var id = shh.newIdentity() | ||||
| 						postData(data._id, id) | ||||
| 
 | ||||
| 						break | ||||
| 
 | ||||
| 						case "shh_post": | ||||
| 						require(1); | ||||
| 
 | ||||
| 						var params = data.args[0]; | ||||
| 						var fields = ["payload", "to", "from"]; | ||||
| 						for(var i = 0; i < fields.length; i++) { | ||||
| 							params[fields[i]] = params[fields[i]] || ""; | ||||
| 						} | ||||
| 						if(typeof params.payload !== "object") { params.payload = [params.payload]; } //params.payload = params.payload.join(""); } | ||||
| 						params.topics = params.topics || []; | ||||
| 						params.priority = params.priority || 1000; | ||||
| 						params.ttl = params.ttl || 100; | ||||
| 
 | ||||
| 						shh.post(params.payload, params.to, params.from, params.topics, params.priority, params.ttl); | ||||
| 
 | ||||
| 						break; | ||||
| 
 | ||||
| 						case "shh_getMessages": | ||||
| 						require(1); | ||||
| 
 | ||||
| 						var m = shh.messages(data.args[0]); | ||||
| 						var messages = JSON.parse(JSON.parse(JSON.stringify(m))); | ||||
| 						postData(data._id, messages); | ||||
| 
 | ||||
| 						break; | ||||
| 
 | ||||
| 						case "ssh_newGroup": | ||||
| 						postData(data._id, ""); | ||||
| 						break; | ||||
| 				function require(args, num) { | ||||
| 					if(args.length < num) { | ||||
| 						throw("required argument count of "+num+" got "+args.length); | ||||
| 					} | ||||
| 				} catch(e) { | ||||
| 					console.log(data.call + ": " + e) | ||||
| 
 | ||||
| 					postData(data._id, null); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 
 | ||||
| 			function post(seed, data) { | ||||
| 				postData(data._id, data) | ||||
| 			} | ||||
| 
 | ||||
| 			function require(args, num) { | ||||
| 				if(args.length < num) { | ||||
| 					throw("required argument count of "+num+" got "+args.length); | ||||
| 				function postData(seed, data) { | ||||
| 					webview.experimental.postMessage(JSON.stringify({data: data, _id: seed})) | ||||
| 				} | ||||
| 				function postEvent(event, id, data) { | ||||
| 					webview.experimental.postMessage(JSON.stringify({data: data, _id: id, _event: event})) | ||||
| 				} | ||||
| 				function onWatchedCb(data, id) { | ||||
| 					var messages = JSON.parse(data) | ||||
| 					postEvent("watched:"+id, messages) | ||||
| 				} | ||||
| 				function onNewBlockCb(block) { | ||||
| 					postEvent("block:new", block) | ||||
| 				} | ||||
| 				function onObjectChangeCb(stateObject) { | ||||
| 					postEvent("object:"+stateObject.address(), stateObject) | ||||
| 				} | ||||
| 				function onStorageChangeCb(storageObject) { | ||||
| 					var ev = ["storage", storageObject.stateAddress, storageObject.address].join(":"); | ||||
| 					postEvent(ev, [storageObject.address, storageObject.value]) | ||||
| 				} | ||||
| 			} | ||||
| 			function postData(seed, data) { | ||||
| 				webview.experimental.postMessage(JSON.stringify({data: data, _id: seed})) | ||||
| 			} | ||||
| 			function postEvent(event, id, data) { | ||||
| 				webview.experimental.postMessage(JSON.stringify({data: data, _id: id, _event: event})) | ||||
| 			} | ||||
| 
 | ||||
| 			function onWatchedCb(data, id) { | ||||
| 				var messages = JSON.parse(data) | ||||
| 				postEvent("watched:"+id, messages) | ||||
| 			} | ||||
| 
 | ||||
| 			function onNewBlockCb(block) { | ||||
| 				postEvent("block:new", block) | ||||
| 			} | ||||
| 			function onObjectChangeCb(stateObject) { | ||||
| 				postEvent("object:"+stateObject.address(), stateObject) | ||||
| 			} | ||||
| 			function onStorageChangeCb(storageObject) { | ||||
| 				var ev = ["storage", storageObject.stateAddress, storageObject.address].join(":"); | ||||
| 				postEvent(ev, [storageObject.address, storageObject.value]) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 		Rectangle { | ||||
| 			id: sizeGrip | ||||
| 			color: "gray" | ||||
|  | ||||
| @ -13,7 +13,6 @@ ApplicationWindow { | ||||
| 	id: root | ||||
| 
 | ||||
| 	property var ethx : Eth.ethx | ||||
| 	property var browser | ||||
| 
 | ||||
| 	width: 1200 | ||||
| 	height: 820 | ||||
| @ -21,6 +20,7 @@ ApplicationWindow { | ||||
| 
 | ||||
| 	title: "Mist" | ||||
| 
 | ||||
|     /* | ||||
| 	// This signal is used by the filter API. The filter API connects using this signal handler from | ||||
| 	// the different QML files and plugins. | ||||
| 	signal messages(var messages, int id); | ||||
| @ -30,6 +30,7 @@ ApplicationWindow { | ||||
| 		messages(data, receiverSeed); | ||||
| 		root.browser.view.messages(data, receiverSeed); | ||||
| 	} | ||||
|     */ | ||||
| 
 | ||||
| 	TextField { | ||||
| 		id: copyElementHax | ||||
| @ -45,8 +46,6 @@ ApplicationWindow { | ||||
| 	// Takes care of loading all default plugins | ||||
| 	Component.onCompleted: { | ||||
| 		var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true}); | ||||
| 		var browser = addPlugin("./browser.qml", {noAdd: true, close: false, section: "ethereum", active: true}); | ||||
| 		root.browser = browser; | ||||
| 		addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true}); | ||||
| 
 | ||||
| 		addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"}); | ||||
| @ -55,17 +54,17 @@ ApplicationWindow { | ||||
| 		addPlugin("./views/pending_tx.qml", {noAdd: true, close: false, section: "legacy"}); | ||||
| 		addPlugin("./views/info.qml", {noAdd: true, close: false, section: "legacy"}); | ||||
| 
 | ||||
| 		addPlugin("./views/jeffcoin/jeffcoin.qml", {noAdd: true, close: false, section: "apps"}) | ||||
| 
 | ||||
| 		mainSplit.setView(wallet.view, wallet.menuItem); | ||||
| 
 | ||||
|         newBrowserTab("http://etherian.io"); | ||||
| 
 | ||||
| 		// Command setup | ||||
| 		gui.sendCommand(0) | ||||
| 	} | ||||
| 
 | ||||
| 	function activeView(view, menuItem) { | ||||
| 		mainSplit.setView(view, menuItem) | ||||
| 		if (view.objectName === "browserView") { | ||||
|         if (view.hideUrl) { | ||||
| 			urlPane.visible = false; | ||||
| 			mainView.anchors.top = rootView.top | ||||
| 		} else { | ||||
| @ -119,6 +118,13 @@ ApplicationWindow { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     function newBrowserTab(url) { | ||||
| 		var window = addPlugin("./browser.qml", {noAdd: true, close: true, section: "apps", active: true}); | ||||
|         window.view.url = url; | ||||
|         window.menuItem.title = "Browser Tab"; | ||||
|         activeView(window.view, window.menuItem); | ||||
|     } | ||||
| 
 | ||||
| 	menuBar: MenuBar { | ||||
| 		Menu { | ||||
| 			title: "File" | ||||
| @ -130,13 +136,6 @@ ApplicationWindow { | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			/* | ||||
| 			 MenuItem { | ||||
| 				 text: "Browser" | ||||
| 				 onTriggered: eth.openBrowser() | ||||
| 			 } | ||||
| 			 */ | ||||
| 
 | ||||
| 			MenuItem { | ||||
| 				text: "Add plugin" | ||||
| 				onTriggered: { | ||||
| @ -146,6 +145,14 @@ ApplicationWindow { | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
|             MenuItem { | ||||
|                 text: "New tab" | ||||
|                 shortcut: "Ctrl+t" | ||||
|                 onTriggered: { | ||||
|                     newBrowserTab("http://etherian.io"); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| 			MenuSeparator {} | ||||
| 
 | ||||
| 			MenuItem { | ||||
| @ -205,21 +212,6 @@ ApplicationWindow { | ||||
| 			} | ||||
| 
 | ||||
| 			MenuSeparator {} | ||||
| 
 | ||||
| 			/* | ||||
| 			 MenuItem { | ||||
| 				 id: miningSpeed | ||||
| 				 text: "Mining: Turbo" | ||||
| 				 onTriggered: { | ||||
| 					 gui.toggleTurboMining() | ||||
| 					 if(text == "Mining: Turbo") { | ||||
| 						 text = "Mining: Normal"; | ||||
| 					 } else { | ||||
| 						 text = "Mining: Turbo"; | ||||
| 					 } | ||||
| 				 } | ||||
| 			 } | ||||
| 			 */ | ||||
| 		} | ||||
| 
 | ||||
| 		Menu { | ||||
| @ -350,9 +342,6 @@ ApplicationWindow { | ||||
| 				views[i].menuItem.setSelection(false) | ||||
| 			} | ||||
| 			view.visible = true | ||||
| 
 | ||||
| 			//menu.border.color = "#CCCCCC" | ||||
| 			//menu.color = "#FFFFFFFF" | ||||
| 			menu.setSelection(true) | ||||
| 		} | ||||
| 
 | ||||
| @ -512,7 +501,15 @@ ApplicationWindow { | ||||
| 
 | ||||
| 						 this.view.destroy() | ||||
| 						 this.destroy() | ||||
|                          for (var i = 0; i < mainSplit.views.length; i++) { | ||||
|                              var view = mainSplit.views[i]; | ||||
|                              if (view.menuItem === this) { | ||||
|                                  mainSplit.views.splice(i, 1); | ||||
|                                  break; | ||||
|                              } | ||||
|                          } | ||||
| 						 gui.removePlugin(this.path) | ||||
|                          activeView(mainSplit.views[0].view, mainSplit.views[0].menuItem); | ||||
| 					 } | ||||
| 				 } | ||||
| 			 } | ||||
| @ -576,7 +573,7 @@ ApplicationWindow { | ||||
| 
 | ||||
| 
 | ||||
| 				 Text { | ||||
| 					 text: "APPS" | ||||
| 					 text: "NET" | ||||
| 					 font.bold: true | ||||
| 					 anchors { | ||||
| 						 left: parent.left | ||||
| @ -653,7 +650,7 @@ ApplicationWindow { | ||||
| 
 | ||||
| 					  Keys.onReturnPressed: { | ||||
| 						  if(/^https?/.test(this.text)) { | ||||
| 							  activeView(root.browser.view, root.browser.menuItem); | ||||
|                               newBrowserTab(this.text); | ||||
| 						  } else { | ||||
| 							  addPlugin(this.text, {close: true, section: "apps"}) | ||||
| 						  } | ||||
|  | ||||
| @ -18,7 +18,6 @@ Rectangle { | ||||
| 	property var identity: "" | ||||
| 	Component.onCompleted: { | ||||
| 		identity = shh.newIdentity() | ||||
| 		console.log("New identity:", identity) | ||||
| 
 | ||||
| 		var t = shh.watch({}, root) | ||||
| 	} | ||||
|  | ||||
| @ -312,23 +312,19 @@ func (self *UiLib) ToAscii(data string) string { | ||||
| } | ||||
| 
 | ||||
| /// Ethereum filter methods
 | ||||
| func (self *UiLib) NewFilter(object map[string]interface{}) (id int) { | ||||
| func (self *UiLib) NewFilter(object map[string]interface{}, view *qml.Common) (id int) { | ||||
| 	filter := qt.NewFilterFromMap(object, self.eth) | ||||
| 	filter.MessageCallback = func(messages state.Messages) { | ||||
| 		self.win.Root().Call("invokeFilterCallback", xeth.ToJSMessages(messages), id) | ||||
| 		view.Call("messages", xeth.ToJSMessages(messages), id) | ||||
| 	} | ||||
| 	id = self.filterManager.InstallFilter(filter) | ||||
| 	return id | ||||
| } | ||||
| 
 | ||||
| func (self *UiLib) NewFilterString(typ string) (id int) { | ||||
| func (self *UiLib) NewFilterString(typ string, view *qml.Common) (id int) { | ||||
| 	filter := core.NewFilter(self.eth) | ||||
| 	filter.BlockCallback = func(block *types.Block) { | ||||
| 		if self.win != nil && self.win.Root() != nil { | ||||
| 			self.win.Root().Call("invokeFilterCallback", "{}", id) | ||||
| 		} else { | ||||
| 			fmt.Println("QML is lagging") | ||||
| 		} | ||||
| 		view.Call("messages", "{}", id) | ||||
| 	} | ||||
| 	id = self.filterManager.InstallFilter(filter) | ||||
| 	return id | ||||
|  | ||||
| @ -5,6 +5,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| @ -251,15 +252,12 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { | ||||
| 		return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Header().Time, sm.bc.CurrentBlock().Header().Time) | ||||
| 	} | ||||
| 
 | ||||
| 	/* XXX | ||||
| 	// New blocks must be within the 15 minute range of the last block.
 | ||||
| 	if diff > int64(15*time.Minute) { | ||||
| 		return ValidationError("Block is too far in the future of last block (> 15 minutes)") | ||||
| 	if block.Time() > time.Now().Unix() { | ||||
| 		return fmt.Errorf("block time is in the future") | ||||
| 	} | ||||
| 	*/ | ||||
| 
 | ||||
| 	// Verify the nonce of the block. Return an error if it's not valid
 | ||||
| 	if !sm.Pow.Verify(block /*block.HashNoNonce(), block.Difficulty, block.Nonce*/) { | ||||
| 	if !sm.Pow.Verify(block) { | ||||
| 		return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Header().Nonce)) | ||||
| 	} | ||||
| 
 | ||||
| @ -287,21 +285,6 @@ func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, paren | ||||
| 			return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) | ||||
| 		} | ||||
| 
 | ||||
| 		/* | ||||
| 			uncleParent := sm.bc.GetBlock(uncle.ParentHash) | ||||
| 			if uncleParent == nil { | ||||
| 				return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) | ||||
| 			} | ||||
| 
 | ||||
| 			if uncleParent.Number().Cmp(new(big.Int).Sub(parent.Number(), big.NewInt(6))) < 0 { | ||||
| 				return UncleError("Uncle too old") | ||||
| 			} | ||||
| 
 | ||||
| 			if knownUncles.Has(string(uncle.Hash())) { | ||||
| 				return UncleError("Uncle in chain") | ||||
| 			} | ||||
| 		*/ | ||||
| 
 | ||||
| 		r := new(big.Int) | ||||
| 		r.Mul(BlockReward, big.NewInt(15)).Div(r, big.NewInt(16)) | ||||
| 
 | ||||
|  | ||||
| @ -7,9 +7,9 @@ import ( | ||||
| 	"math/big" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/crypto/secp256k1" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/ethereum/go-ethereum/rlp" | ||||
| 	"github.com/obscuren/secp256k1-go" | ||||
| ) | ||||
| 
 | ||||
| func IsContractAddr(addr []byte) bool { | ||||
|  | ||||
							
								
								
									
										116
									
								
								crypto/crypto.go
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								crypto/crypto.go
									
									
									
									
									
								
							| @ -1,16 +1,25 @@ | ||||
| package crypto | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/aes" | ||||
| 	"crypto/cipher" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/elliptic" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/sha256" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 
 | ||||
| 	"code.google.com/p/go-uuid/uuid" | ||||
| 	"code.google.com/p/go.crypto/pbkdf2" | ||||
| 	"code.google.com/p/go.crypto/ripemd160" | ||||
| 	"github.com/ethereum/go-ethereum/crypto/secp256k1" | ||||
| 	"github.com/ethereum/go-ethereum/crypto/sha3" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/obscuren/ecies" | ||||
| 	"github.com/obscuren/secp256k1-go" | ||||
| 	"github.com/obscuren/sha3" | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| @ -101,7 +110,11 @@ func SigToPub(hash, sig []byte) *ecdsa.PublicKey { | ||||
| } | ||||
| 
 | ||||
| func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { | ||||
| 	sig, err = secp256k1.Sign(hash, prv.D.Bytes()) | ||||
| 	if len(hash) != 32 { | ||||
| 		return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) | ||||
| 	} | ||||
| 
 | ||||
| 	sig, err = secp256k1.Sign(hash, ethutil.LeftPadBytes(prv.D.Bytes(), prv.Params().BitSize/8)) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| @ -113,3 +126,100 @@ func Decrypt(prv *ecdsa.PrivateKey, ct []byte) ([]byte, error) { | ||||
| 	key := ecies.ImportECDSA(prv) | ||||
| 	return key.Decrypt(rand.Reader, ct, nil, nil) | ||||
| } | ||||
| 
 | ||||
| // creates a Key and stores that in the given KeyStore by decrypting a presale key JSON
 | ||||
| func ImportPreSaleKey(keyStore KeyStore2, keyJSON []byte, password string) (*Key, error) { | ||||
| 	key, err := decryptPreSaleKey(keyJSON, password) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	id := uuid.NewRandom() | ||||
| 	key.Id = &id | ||||
| 	err = keyStore.StoreKey(key, password) | ||||
| 	return key, err | ||||
| } | ||||
| 
 | ||||
| func decryptPreSaleKey(fileContent []byte, password string) (key *Key, err error) { | ||||
| 	preSaleKeyStruct := struct { | ||||
| 		EncSeed string | ||||
| 		EthAddr string | ||||
| 		Email   string | ||||
| 		BtcAddr string | ||||
| 	}{} | ||||
| 	err = json.Unmarshal(fileContent, &preSaleKeyStruct) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	encSeedBytes, err := hex.DecodeString(preSaleKeyStruct.EncSeed) | ||||
| 	iv := encSeedBytes[:16] | ||||
| 	cipherText := encSeedBytes[16:] | ||||
| 	/* | ||||
| 		See https://github.com/ethereum/pyethsaletool
 | ||||
| 
 | ||||
| 		pyethsaletool generates the encryption key from password by | ||||
| 		2000 rounds of PBKDF2 with HMAC-SHA-256 using password as salt (:(). | ||||
| 		16 byte key length within PBKDF2 and resulting key is used as AES key | ||||
| 	*/ | ||||
| 	passBytes := []byte(password) | ||||
| 	derivedKey := pbkdf2.Key(passBytes, passBytes, 2000, 16, sha256.New) | ||||
| 	plainText, err := aesCBCDecrypt(derivedKey, cipherText, iv) | ||||
| 	ethPriv := Sha3(plainText) | ||||
| 	ecKey := ToECDSA(ethPriv) | ||||
| 	key = &Key{ | ||||
| 		Id:         nil, | ||||
| 		PrivateKey: ecKey, | ||||
| 	} | ||||
| 	derivedAddr := ethutil.Bytes2Hex(key.Address()) | ||||
| 	expectedAddr := preSaleKeyStruct.EthAddr | ||||
| 	if derivedAddr != expectedAddr { | ||||
| 		err = errors.New("decrypted addr not equal to expected addr") | ||||
| 	} | ||||
| 	return key, err | ||||
| } | ||||
| 
 | ||||
| func aesCBCDecrypt(key []byte, cipherText []byte, iv []byte) (plainText []byte, err error) { | ||||
| 	aesBlock, err := aes.NewCipher(key) | ||||
| 	if err != nil { | ||||
| 		return plainText, err | ||||
| 	} | ||||
| 	decrypter := cipher.NewCBCDecrypter(aesBlock, iv) | ||||
| 	paddedPlainText := make([]byte, len(cipherText)) | ||||
| 	decrypter.CryptBlocks(paddedPlainText, cipherText) | ||||
| 	plainText = PKCS7Unpad(paddedPlainText) | ||||
| 	if plainText == nil { | ||||
| 		err = errors.New("Decryption failed: PKCS7Unpad failed after decryption") | ||||
| 	} | ||||
| 	return plainText, err | ||||
| } | ||||
| 
 | ||||
| // From https://leanpub.com/gocrypto/read#leanpub-auto-block-cipher-modes
 | ||||
| func PKCS7Pad(in []byte) []byte { | ||||
| 	padding := 16 - (len(in) % 16) | ||||
| 	if padding == 0 { | ||||
| 		padding = 16 | ||||
| 	} | ||||
| 	for i := 0; i < padding; i++ { | ||||
| 		in = append(in, byte(padding)) | ||||
| 	} | ||||
| 	return in | ||||
| } | ||||
| 
 | ||||
| func PKCS7Unpad(in []byte) []byte { | ||||
| 	if len(in) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	padding := in[len(in)-1] | ||||
| 	if int(padding) > len(in) || padding > aes.BlockSize { | ||||
| 		return nil | ||||
| 	} else if padding == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	for i := len(in) - 1; i > len(in)-int(padding)-1; i-- { | ||||
| 		if in[i] != padding { | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| 	return in[:len(in)-int(padding)] | ||||
| } | ||||
|  | ||||
| @ -7,8 +7,8 @@ import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto/secp256k1" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/obscuren/secp256k1-go" | ||||
| ) | ||||
| 
 | ||||
| // These tests are sanity checks.
 | ||||
| @ -52,7 +52,7 @@ func BenchmarkSha3(b *testing.B) { | ||||
| } | ||||
| 
 | ||||
| func Test0Key(t *testing.T) { | ||||
| 
 | ||||
| 	t.Skip() | ||||
| 	key := ethutil.Hex2Bytes("1111111111111111111111111111111111111111111111111111111111111111") | ||||
| 
 | ||||
| 	p, err := secp256k1.GeneratePubKey(key) | ||||
| @ -60,3 +60,15 @@ func Test0Key(t *testing.T) { | ||||
| 	fmt.Printf("%x\n", p) | ||||
| 	fmt.Printf("%v %x\n", err, addr) | ||||
| } | ||||
| 
 | ||||
| func TestInvalidSign(t *testing.T) { | ||||
| 	_, err := Sign(make([]byte, 1), nil) | ||||
| 	if err == nil { | ||||
| 		t.Errorf("expected sign with hash 1 byte to error") | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = Sign(make([]byte, 33), nil) | ||||
| 	if err == nil { | ||||
| 		t.Errorf("expected sign with hash 33 byte to error") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -57,7 +57,7 @@ type encryptedKeyJSON struct { | ||||
| 
 | ||||
| func (k *Key) Address() []byte { | ||||
| 	pubBytes := FromECDSAPub(&k.PrivateKey.PublicKey) | ||||
| 	return Sha3(pubBytes)[12:] | ||||
| 	return Sha3(pubBytes[1:])[12:] | ||||
| } | ||||
| 
 | ||||
| func (k *Key) MarshalJSON() (j []byte, err error) { | ||||
| @ -99,9 +99,10 @@ func NewKey(rand io.Reader) *Key { | ||||
| 	privateKeyMarshalled := elliptic.Marshal(S256(), x, y) | ||||
| 	privateKeyECDSA := ToECDSA(privateKeyMarshalled) | ||||
| 
 | ||||
| 	key := new(Key) | ||||
| 	id := uuid.NewRandom() | ||||
| 	key.Id = &id | ||||
| 	key.PrivateKey = privateKeyECDSA | ||||
| 	key := &Key{ | ||||
| 		Id:         &id, | ||||
| 		PrivateKey: privateKeyECDSA, | ||||
| 	} | ||||
| 	return key | ||||
| } | ||||
|  | ||||
| @ -178,22 +178,10 @@ func DecryptKey(ks keyStorePassphrase, keyId *uuid.UUID, auth string) (keyBytes | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	AES256Block, err := aes.NewCipher(derivedKey) | ||||
| 	plainText, err := aesCBCDecrypt(derivedKey, cipherText, iv) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	AES256CBCDecrypter := cipher.NewCBCDecrypter(AES256Block, iv) | ||||
| 	paddedPlainText := make([]byte, len(cipherText)) | ||||
| 	AES256CBCDecrypter.CryptBlocks(paddedPlainText, cipherText) | ||||
| 
 | ||||
| 	plainText := PKCS7Unpad(paddedPlainText) | ||||
| 	if plainText == nil { | ||||
| 		err = errors.New("Decryption failed: PKCS7Unpad failed after decryption") | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	keyBytes = plainText[:len(plainText)-32] | ||||
| 	keyBytesHash := plainText[len(plainText)-32:] | ||||
| 	if !bytes.Equal(Sha3(keyBytes), keyBytesHash) { | ||||
| @ -211,35 +199,3 @@ func getEntropyCSPRNG(n int) []byte { | ||||
| 	} | ||||
| 	return mainBuff | ||||
| } | ||||
| 
 | ||||
| // From https://leanpub.com/gocrypto/read#leanpub-auto-block-cipher-modes
 | ||||
| func PKCS7Pad(in []byte) []byte { | ||||
| 	padding := 16 - (len(in) % 16) | ||||
| 	if padding == 0 { | ||||
| 		padding = 16 | ||||
| 	} | ||||
| 	for i := 0; i < padding; i++ { | ||||
| 		in = append(in, byte(padding)) | ||||
| 	} | ||||
| 	return in | ||||
| } | ||||
| 
 | ||||
| func PKCS7Unpad(in []byte) []byte { | ||||
| 	if len(in) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	padding := in[len(in)-1] | ||||
| 	if int(padding) > len(in) || padding > aes.BlockSize { | ||||
| 		return nil | ||||
| 	} else if padding == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	for i := len(in) - 1; i > len(in)-int(padding)-1; i-- { | ||||
| 		if in[i] != padding { | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| 	return in[:len(in)-int(padding)] | ||||
| } | ||||
|  | ||||
| @ -83,3 +83,16 @@ func TestKeyStorePassphraseDecryptionFail(t *testing.T) { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestImportPreSaleKey(t *testing.T) { | ||||
| 	// file content of a presale key file generated with:
 | ||||
| 	// python pyethsaletool.py genwallet
 | ||||
| 	// with password "foo"
 | ||||
| 	fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}" | ||||
| 	ks := NewKeyStorePassphrase(DefaultDataDir()) | ||||
| 	pass := "foo" | ||||
| 	_, err := ImportPreSaleKey(ks, []byte(fileContent), pass) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -3,8 +3,8 @@ package crypto | ||||
| import ( | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto/secp256k1" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/obscuren/secp256k1-go" | ||||
| ) | ||||
| 
 | ||||
| type KeyPair struct { | ||||
|  | ||||
							
								
								
									
										24
									
								
								crypto/secp256k1/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								crypto/secp256k1/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| # Compiled Object files, Static and Dynamic libs (Shared Objects) | ||||
| *.o | ||||
| *.a | ||||
| *.so | ||||
| 
 | ||||
| # Folders | ||||
| _obj | ||||
| _test | ||||
| 
 | ||||
| # Architecture specific extensions/prefixes | ||||
| *.[568vq] | ||||
| [568vq].out | ||||
| 
 | ||||
| *.cgo1.go | ||||
| *.cgo2.c | ||||
| _cgo_defun.c | ||||
| _cgo_gotypes.go | ||||
| _cgo_export.* | ||||
| 
 | ||||
| _testmain.go | ||||
| 
 | ||||
| *.exe | ||||
| 
 | ||||
| *~ | ||||
							
								
								
									
										22
									
								
								crypto/secp256k1/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								crypto/secp256k1/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| secp256k1-go | ||||
| ======= | ||||
| 
 | ||||
| golang secp256k1 library | ||||
| 
 | ||||
| Implements cryptographic operations for the secp256k1 ECDSA curve used by Bitcoin. | ||||
| 
 | ||||
| Installing | ||||
| === | ||||
| ``` | ||||
| sudo apt-get install gmp-dev | ||||
| ``` | ||||
| 
 | ||||
| Now compiles with cgo! | ||||
| 
 | ||||
| Test | ||||
| === | ||||
| 
 | ||||
| To run tests do | ||||
| ``` | ||||
| go tests | ||||
| ``` | ||||
							
								
								
									
										192
									
								
								crypto/secp256k1/notes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								crypto/secp256k1/notes.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,192 @@ | ||||
| package secp256k1 | ||||
| 
 | ||||
| /* | ||||
| <HaltingState> sipa, int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed); | ||||
| <HaltingState> is that how i generate private/public keys? | ||||
| <sipa> HaltingState: you pass in a random 32-byte string as seckey | ||||
| <sipa> HaltingState: if it is valid, the corresponding pubkey is put in pubkey | ||||
| <sipa> and true is returned | ||||
| <sipa> otherwise, false is returned | ||||
| <sipa> around 1 in 2^128 32-byte strings are invalid, so the odds of even ever seeing one is extremely rare | ||||
| 
 | ||||
| <sipa> private keys are mathematically numbers | ||||
| <sipa> each has a corresponding point on the curve as public key | ||||
| <sipa> a private key is just a number | ||||
| <sipa> a public key is a point with x/y coordinates | ||||
| <sipa> almost every 256-bit number is a valid private key (one with a point on the curve corresponding to it) | ||||
| <sipa> HaltingState: ok? | ||||
| 
 | ||||
| <sipa> more than half of random points are not on the curve | ||||
| <sipa> and actually, it is less than  the square root, not less than half, sorry :) | ||||
| !!! | ||||
| <sipa> a private key is a NUMBER | ||||
| <sipa> a public key is a POINT | ||||
| <gmaxwell> half the x,y values in the field are not on the curve, a private key is an integer. | ||||
| 
 | ||||
| <sipa> HaltingState: yes, n,q = private keys; N,Q = corresponding public keys (N=n*G, Q=q*G); then it follows that n*Q = n*q*G = q*n*G = q*N | ||||
| <sipa> that's the reason ECDH works | ||||
| <sipa> multiplication is associative and commutativ | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
| <HaltingState> sipa, ok; i am doing compact signatures and I want to know; can someone change the signature to get another valid signature for same message without the private key | ||||
| <HaltingState> because i know they can do that for the normal 72 byte signatures that openssl was putting out | ||||
| <sipa> HaltingState: if you don't enforce non-malleability, yes | ||||
| <sipa> HaltingState: if you force the highest bit of t | ||||
| 
 | ||||
| <sipa> it _creates_ signatures that already satisfy that condition | ||||
| <sipa> but it will accept ones that don't | ||||
| <sipa> maybe i should change that, and be strict | ||||
| <HaltingState> yes; i want some way to know signature is valid but fails malleability | ||||
| <sipa> well if the highest bit of S is 1, you can take its complement | ||||
| <sipa> and end up with a valid signature | ||||
| <sipa> that is canonical | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
| 
 | ||||
| <HaltingState> sipa, I am signing messages and highest bit of the compact signature is 1!!! | ||||
| <HaltingState>  if (b & 0x80) == 0x80 { | ||||
| <HaltingState>   log.Panic("b= %v b2= %v \n", b, b&0x80) | ||||
| <HaltingState>  } | ||||
| <sipa> what bit? | ||||
| * Pengoo has quit (Ping timeout: 272 seconds) | ||||
| <HaltingState> the highest bit of the first byte of signature | ||||
| <sipa> it's the highest bit of S | ||||
| <sipa> so the 32nd byte | ||||
| <HaltingState> wtf | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
|  For instance, nonces are used in HTTP digest access authentication to calculate an MD5 digest | ||||
|  of the password. The nonces are different each time the 401 authentication challenge | ||||
|  response code is presented, thus making replay attacks virtually impossible. | ||||
| 
 | ||||
| can verify client/server match without sending password over network | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
| <hanihani> one thing I dont get about armory for instance, | ||||
| is how the hot-wallet can generate new addresses without | ||||
| knowing the master key | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
| <HaltingState> i am yelling at the telehash people for using secp256r1 | ||||
| instead of secp256k1; they thing r1 is "more secure" despite fact that | ||||
| there is no implementation that works and wrapping it is now taking | ||||
| up massive time, lol | ||||
| <gmaxwell> ... | ||||
| 
 | ||||
| <gmaxwell> You know that the *r curves are selected via an undisclosed | ||||
| secret process, right? | ||||
| <gmaxwell> HaltingState: telehash is offtopic for this channel. | ||||
| */ | ||||
| /* | ||||
|  For instance, nonces are used in HTTP digest access authentication to calculate an MD5 digest | ||||
|  of the password. The nonces are different each time the 401 authentication challenge | ||||
|  response code is presented, thus making replay attacks virtually impossible. | ||||
| 
 | ||||
| can verify client/server match without sending password over network | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
| void secp256k1_start(void); | ||||
| void secp256k1_stop(void); | ||||
| 
 | ||||
|  * Verify an ECDSA signature. | ||||
|  *  Returns: 1: correct signature | ||||
|  *           0: incorrect signature | ||||
|  *          -1: invalid public key | ||||
|  *          -2: invalid signature | ||||
|  * | ||||
| int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, | ||||
|                            const unsigned char *sig, int siglen, | ||||
|                            const unsigned char *pubkey, int pubkeylen); | ||||
| 
 | ||||
| http://www.nilsschneider.net/2013/01/28/recovering-bitcoin-private-keys.html
 | ||||
| 
 | ||||
| Why did this work? ECDSA requires a random number for each signature. If this random | ||||
| number is ever used twice with the same private key it can be recovered. | ||||
| This transaction was generated by a hardware bitcoin wallet using a pseudo-random number | ||||
| generator that was returning the same “random” number every time. | ||||
| 
 | ||||
| Nonce is 32 bytes? | ||||
| 
 | ||||
|  * Create an ECDSA signature. | ||||
|  *  Returns: 1: signature created | ||||
|  *           0: nonce invalid, try another one | ||||
|  *  In:      msg:    the message being signed | ||||
|  *           msglen: the length of the message being signed | ||||
|  *           seckey: pointer to a 32-byte secret key (assumed to be valid) | ||||
|  *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG) | ||||
|  *  Out:     sig:    pointer to a 72-byte array where the signature will be placed. | ||||
|  *           siglen: pointer to an int, which will be updated to the signature length (<=72). | ||||
|  * | ||||
| int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen, | ||||
|                          unsigned char *sig, int *siglen, | ||||
|                          const unsigned char *seckey, | ||||
|                          const unsigned char *nonce); | ||||
| 
 | ||||
| 
 | ||||
|  * Create a compact ECDSA signature (64 byte + recovery id). | ||||
|  *  Returns: 1: signature created | ||||
|  *           0: nonce invalid, try another one | ||||
|  *  In:      msg:    the message being signed | ||||
|  *           msglen: the length of the message being signed | ||||
|  *           seckey: pointer to a 32-byte secret key (assumed to be valid) | ||||
|  *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG) | ||||
|  *  Out:     sig:    pointer to a 64-byte array where the signature will be placed. | ||||
|  *           recid:  pointer to an int, which will be updated to contain the recovery id. | ||||
|  * | ||||
| int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen, | ||||
|                                  unsigned char *sig64, | ||||
|                                  const unsigned char *seckey, | ||||
|                                  const unsigned char *nonce, | ||||
|                                  int *recid); | ||||
| 
 | ||||
|  * Recover an ECDSA public key from a compact signature. | ||||
|  *  Returns: 1: public key succesfully recovered (which guarantees a correct signature). | ||||
|  *           0: otherwise. | ||||
|  *  In:      msg:        the message assumed to be signed | ||||
|  *           msglen:     the length of the message | ||||
|  *           compressed: whether to recover a compressed or uncompressed pubkey | ||||
|  *           recid:      the recovery id (as returned by ecdsa_sign_compact) | ||||
|  *  Out:     pubkey:     pointer to a 33 or 65 byte array to put the pubkey. | ||||
|  *           pubkeylen:  pointer to an int that will contain the pubkey length. | ||||
|  * | ||||
| 
 | ||||
| recovery id is between 0 and 3 | ||||
| 
 | ||||
| int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, | ||||
|                                     const unsigned char *sig64, | ||||
|                                     unsigned char *pubkey, int *pubkeylen, | ||||
|                                     int compressed, int recid); | ||||
| 
 | ||||
| 
 | ||||
|  * Verify an ECDSA secret key. | ||||
|  *  Returns: 1: secret key is valid | ||||
|  *           0: secret key is invalid | ||||
|  *  In:      seckey: pointer to a 32-byte secret key | ||||
|  * | ||||
| int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey); | ||||
| 
 | ||||
| ** Just validate a public key. | ||||
|  *  Returns: 1: valid public key | ||||
|  *           0: invalid public key | ||||
|  * | ||||
| int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen); | ||||
| 
 | ||||
| ** Compute the public key for a secret key. | ||||
|  *  In:     compressed: whether the computed public key should be compressed | ||||
|  *          seckey:     pointer to a 32-byte private key. | ||||
|  *  Out:    pubkey:     pointer to a 33-byte (if compressed) or 65-byte (if uncompressed) | ||||
|  *                      area to store the public key. | ||||
|  *          pubkeylen:  pointer to int that will be updated to contains the pubkey's | ||||
|  *                      length. | ||||
|  *  Returns: 1: secret was valid, public key stores | ||||
|  *           0: secret was invalid, try again. | ||||
|  * | ||||
| int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed); | ||||
| */ | ||||
							
								
								
									
										304
									
								
								crypto/secp256k1/secp256.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								crypto/secp256k1/secp256.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,304 @@ | ||||
| package secp256k1 | ||||
| 
 | ||||
| /* | ||||
| #cgo CFLAGS: -std=gnu99 -Wno-error | ||||
| #cgo darwin CFLAGS: -I/usr/local/include | ||||
| #cgo LDFLAGS: -lgmp | ||||
| #cgo darwin LDFLAGS: -L/usr/local/lib | ||||
| #define USE_FIELD_10X26 | ||||
| #define USE_NUM_GMP | ||||
| #define USE_FIELD_INV_BUILTIN | ||||
| #include "./secp256k1/src/secp256k1.c" | ||||
| */ | ||||
| import "C" | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| //#define USE_FIELD_5X64
 | ||||
| 
 | ||||
| /* | ||||
|    Todo: | ||||
|    > Centralize key management in module | ||||
|    > add pubkey/private key struct | ||||
|    > Dont let keys leave module; address keys as ints | ||||
| 
 | ||||
|    > store private keys in buffer and shuffle (deters persistance on swap disc) | ||||
|    > Byte permutation (changing) | ||||
|    > xor with chaning random block (to deter scanning memory for 0x63) (stream cipher?) | ||||
| 
 | ||||
|    On Disk | ||||
|    > Store keys in wallets | ||||
|    > use slow key derivation function for wallet encryption key (2 seconds) | ||||
| */ | ||||
| 
 | ||||
| func init() { | ||||
| 	C.secp256k1_start() //takes 10ms to 100ms
 | ||||
| } | ||||
| 
 | ||||
| func Stop() { | ||||
| 	C.secp256k1_stop() | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| int secp256k1_ecdsa_pubkey_create( | ||||
|     unsigned char *pubkey, int *pubkeylen, | ||||
|     const unsigned char *seckey, int compressed); | ||||
| */ | ||||
| 
 | ||||
| /** Compute the public key for a secret key. | ||||
|  *  In:     compressed: whether the computed public key should be compressed | ||||
|  *          seckey:     pointer to a 32-byte private key. | ||||
|  *  Out:    pubkey:     pointer to a 33-byte (if compressed) or 65-byte (if uncompressed) | ||||
|  *                      area to store the public key. | ||||
|  *          pubkeylen:  pointer to int that will be updated to contains the pubkey's | ||||
|  *                      length. | ||||
|  *  Returns: 1: secret was valid, public key stores | ||||
|  *           0: secret was invalid, try again. | ||||
|  */ | ||||
| 
 | ||||
| //pubkey, seckey
 | ||||
| 
 | ||||
| func GenerateKeyPair() ([]byte, []byte) { | ||||
| 
 | ||||
| 	pubkey_len := C.int(65) | ||||
| 	const seckey_len = 32 | ||||
| 
 | ||||
| 	var pubkey []byte = make([]byte, pubkey_len) | ||||
| 	var seckey []byte = RandByte(seckey_len) | ||||
| 
 | ||||
| 	var pubkey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&pubkey[0])) | ||||
| 	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) | ||||
| 
 | ||||
| 	ret := C.secp256k1_ecdsa_pubkey_create( | ||||
| 		pubkey_ptr, &pubkey_len, | ||||
| 		seckey_ptr, 0) | ||||
| 
 | ||||
| 	if ret != C.int(1) { | ||||
| 		return GenerateKeyPair() //invalid secret, try again
 | ||||
| 	} | ||||
| 	return pubkey, seckey | ||||
| } | ||||
| 
 | ||||
| func GeneratePubKey(seckey []byte) ([]byte, error) { | ||||
| 	pubkey_len := C.int(65) | ||||
| 	const seckey_len = 32 | ||||
| 
 | ||||
| 	var pubkey []byte = make([]byte, pubkey_len) | ||||
| 
 | ||||
| 	var pubkey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&pubkey[0])) | ||||
| 	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) | ||||
| 
 | ||||
| 	ret := C.secp256k1_ecdsa_pubkey_create( | ||||
| 		pubkey_ptr, &pubkey_len, | ||||
| 		seckey_ptr, 0) | ||||
| 
 | ||||
| 	if ret != C.int(1) { | ||||
| 		return nil, errors.New("Unable to generate pubkey from seckey") | ||||
| 	} | ||||
| 
 | ||||
| 	return pubkey, nil | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| *  Create a compact ECDSA signature (64 byte + recovery id). | ||||
| *  Returns: 1: signature created | ||||
| *           0: nonce invalid, try another one | ||||
| *  In:      msg:    the message being signed | ||||
| *           msglen: the length of the message being signed | ||||
| *           seckey: pointer to a 32-byte secret key (assumed to be valid) | ||||
| *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG) | ||||
| *  Out:     sig:    pointer to a 64-byte array where the signature will be placed. | ||||
| *           recid:  pointer to an int, which will be updated to contain the recovery id. | ||||
|  */ | ||||
| 
 | ||||
| /* | ||||
| int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen, | ||||
|                                  unsigned char *sig64, | ||||
|                                  const unsigned char *seckey, | ||||
|                                  const unsigned char *nonce, | ||||
|                                  int *recid); | ||||
| */ | ||||
| 
 | ||||
| func Sign(msg []byte, seckey []byte) ([]byte, error) { | ||||
| 	//var nonce []byte = RandByte(32)
 | ||||
| 	nonce := make([]byte, 32) | ||||
| 	for i := range msg { | ||||
| 		nonce[i] = msg[i] ^ seckey[i] | ||||
| 	} | ||||
| 
 | ||||
| 	var sig []byte = make([]byte, 65) | ||||
| 	var recid C.int | ||||
| 
 | ||||
| 	var msg_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&msg[0])) | ||||
| 	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) | ||||
| 	var nonce_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&nonce[0])) | ||||
| 	var sig_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&sig[0])) | ||||
| 
 | ||||
| 	if C.secp256k1_ecdsa_seckey_verify(seckey_ptr) != C.int(1) { | ||||
| 		return nil, errors.New("Invalid secret key") | ||||
| 	} | ||||
| 
 | ||||
| 	ret := C.secp256k1_ecdsa_sign_compact( | ||||
| 		msg_ptr, C.int(len(msg)), | ||||
| 		sig_ptr, | ||||
| 		seckey_ptr, | ||||
| 		nonce_ptr, | ||||
| 		&recid) | ||||
| 
 | ||||
| 	sig[64] = byte(int(recid)) | ||||
| 
 | ||||
| 	if ret != C.int(1) { | ||||
| 		// nonce invalid, retry
 | ||||
| 		return Sign(msg, seckey) | ||||
| 	} | ||||
| 
 | ||||
| 	return sig, nil | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| * Verify an ECDSA secret key. | ||||
| *  Returns: 1: secret key is valid | ||||
| *           0: secret key is invalid | ||||
| *  In:      seckey: pointer to a 32-byte secret key | ||||
|  */ | ||||
| 
 | ||||
| func VerifySeckeyValidity(seckey []byte) error { | ||||
| 	if len(seckey) != 32 { | ||||
| 		return errors.New("priv key is not 32 bytes") | ||||
| 	} | ||||
| 	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) | ||||
| 	ret := C.secp256k1_ecdsa_seckey_verify(seckey_ptr) | ||||
| 	if int(ret) != 1 { | ||||
| 		return errors.New("invalid seckey") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| * Validate a public key. | ||||
| *  Returns: 1: valid public key | ||||
| *           0: invalid public key | ||||
|  */ | ||||
| 
 | ||||
| func VerifyPubkeyValidity(pubkey []byte) error { | ||||
| 	if len(pubkey) != 65 { | ||||
| 		return errors.New("pub key is not 65 bytes") | ||||
| 	} | ||||
| 	var pubkey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&pubkey[0])) | ||||
| 	ret := C.secp256k1_ecdsa_pubkey_verify(pubkey_ptr, 65) | ||||
| 	if int(ret) != 1 { | ||||
| 		return errors.New("invalid pubkey") | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func VerifySignatureValidity(sig []byte) bool { | ||||
| 	//64+1
 | ||||
| 	if len(sig) != 65 { | ||||
| 		return false | ||||
| 	} | ||||
| 	//malleability check, highest bit must be 1
 | ||||
| 	if (sig[32] & 0x80) == 0x80 { | ||||
| 		return false | ||||
| 	} | ||||
| 	//recovery id check
 | ||||
| 	if sig[64] >= 4 { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| //for compressed signatures, does not need pubkey
 | ||||
| func VerifySignature(msg []byte, sig []byte, pubkey1 []byte) error { | ||||
| 	if msg == nil || sig == nil || pubkey1 == nil { | ||||
| 		return errors.New("inputs must be non-nil") | ||||
| 	} | ||||
| 	if len(sig) != 65 { | ||||
| 		return errors.New("invalid signature length") | ||||
| 	} | ||||
| 	if len(pubkey1) != 65 { | ||||
| 		return errors.New("Invalid public key length") | ||||
| 	} | ||||
| 
 | ||||
| 	//to enforce malleability, highest bit of S must be 0
 | ||||
| 	//S starts at 32nd byte
 | ||||
| 	if (sig[32] & 0x80) == 0x80 { //highest bit must be 1
 | ||||
| 		return errors.New("Signature not malleable") | ||||
| 	} | ||||
| 
 | ||||
| 	if sig[64] >= 4 { | ||||
| 		return errors.New("Recover byte invalid") | ||||
| 	} | ||||
| 
 | ||||
| 	// if pubkey recovered, signature valid
 | ||||
| 	pubkey2, err := RecoverPubkey(msg, sig) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if len(pubkey2) != 65 { | ||||
| 		return errors.New("Invalid recovered public key length") | ||||
| 	} | ||||
| 	if !bytes.Equal(pubkey1, pubkey2) { | ||||
| 		return errors.New("Public key does not match recovered public key") | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, | ||||
|                                     const unsigned char *sig64, | ||||
|                                     unsigned char *pubkey, int *pubkeylen, | ||||
|                                     int compressed, int recid); | ||||
| */ | ||||
| 
 | ||||
| /* | ||||
|  * Recover an ECDSA public key from a compact signature. | ||||
|  *  Returns: 1: public key succesfully recovered (which guarantees a correct signature). | ||||
|  *           0: otherwise. | ||||
|  *  In:      msg:        the message assumed to be signed | ||||
|  *           msglen:     the length of the message | ||||
|  *           compressed: whether to recover a compressed or uncompressed pubkey | ||||
|  *           recid:      the recovery id (as returned by ecdsa_sign_compact) | ||||
|  *  Out:     pubkey:     pointer to a 33 or 65 byte array to put the pubkey. | ||||
|  *           pubkeylen:  pointer to an int that will contain the pubkey length. | ||||
|  */ | ||||
| 
 | ||||
| //recovers the public key from the signature
 | ||||
| //recovery of pubkey means correct signature
 | ||||
| func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) { | ||||
| 	if len(sig) != 65 { | ||||
| 		return nil, errors.New("Invalid signature length") | ||||
| 	} | ||||
| 
 | ||||
| 	var pubkey []byte = make([]byte, 65) | ||||
| 
 | ||||
| 	var msg_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&msg[0])) | ||||
| 	var sig_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&sig[0])) | ||||
| 	var pubkey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&pubkey[0])) | ||||
| 
 | ||||
| 	var pubkeylen C.int | ||||
| 
 | ||||
| 	ret := C.secp256k1_ecdsa_recover_compact( | ||||
| 		msg_ptr, C.int(len(msg)), | ||||
| 		sig_ptr, | ||||
| 		pubkey_ptr, &pubkeylen, | ||||
| 		C.int(0), C.int(sig[64]), | ||||
| 	) | ||||
| 
 | ||||
| 	if ret == C.int(0) { | ||||
| 		return nil, errors.New("Failed to recover public key") | ||||
| 	} else if pubkeylen != C.int(65) { | ||||
| 		return nil, errors.New("Impossible Error: Invalid recovered public key length") | ||||
| 	} else { | ||||
| 		return pubkey, nil | ||||
| 	} | ||||
| 	return nil, errors.New("Impossible Error: func RecoverPubkey has reached an unreachable state") | ||||
| } | ||||
							
								
								
									
										96
									
								
								crypto/secp256k1/secp256_rand.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								crypto/secp256k1/secp256_rand.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | ||||
| package secp256k1 | ||||
| 
 | ||||
| import ( | ||||
| 	crand "crypto/rand" | ||||
| 	"io" | ||||
| 	mrand "math/rand" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| /* | ||||
| Note: | ||||
| 
 | ||||
| - On windows cryto/rand uses CrytoGenRandom which uses RC4 which is insecure | ||||
| - Android random number generator is known to be insecure. | ||||
| - Linux uses /dev/urandom , which is thought to be secure and uses entropy pool | ||||
| 
 | ||||
| Therefore the output is salted. | ||||
| */ | ||||
| 
 | ||||
| //finalizer from MurmerHash3
 | ||||
| func mmh3f(key uint64) uint64 { | ||||
| 	key ^= key >> 33 | ||||
| 	key *= 0xff51afd7ed558ccd | ||||
| 	key ^= key >> 33 | ||||
| 	key *= 0xc4ceb9fe1a85ec53 | ||||
| 	key ^= key >> 33 | ||||
| 	return key | ||||
| } | ||||
| 
 | ||||
| //knuth hash
 | ||||
| func knuth_hash(in []byte) uint64 { | ||||
| 	var acc uint64 = 3074457345618258791 | ||||
| 	for i := 0; i < len(in); i++ { | ||||
| 		acc += uint64(in[i]) | ||||
| 		acc *= 3074457345618258799 | ||||
| 	} | ||||
| 	return acc | ||||
| } | ||||
| 
 | ||||
| var _rand *mrand.Rand | ||||
| 
 | ||||
| func init() { | ||||
| 	var seed1 uint64 = mmh3f(uint64(time.Now().UnixNano())) | ||||
| 	var seed2 uint64 = knuth_hash([]byte(strings.Join(os.Environ(), ""))) | ||||
| 	var seed3 uint64 = mmh3f(uint64(os.Getpid())) | ||||
| 
 | ||||
| 	_rand = mrand.New(mrand.NewSource(int64(seed1 ^ seed2 ^ seed3))) | ||||
| } | ||||
| 
 | ||||
| func saltByte(buff []byte) []byte { | ||||
| 	for i := 0; i < len(buff); i++ { | ||||
| 		var v uint64 = uint64(_rand.Int63()) | ||||
| 		var b byte | ||||
| 		for j := 0; j < 8; j++ { | ||||
| 			b ^= byte(v & 0xff) | ||||
| 			v = v >> 8 | ||||
| 		} | ||||
| 		buff[i] = b | ||||
| 	} | ||||
| 	return buff | ||||
| } | ||||
| 
 | ||||
| //On Unix-like systems, Reader reads from /dev/urandom.
 | ||||
| //On Windows systems, Reader uses the CryptGenRandom API.
 | ||||
| 
 | ||||
| //use entropy pool etc and cryptographic random number generator
 | ||||
| //mix in time
 | ||||
| //mix in mix in cpu cycle count
 | ||||
| func RandByte(n int) []byte { | ||||
| 	buff := make([]byte, n) | ||||
| 	ret, err := io.ReadFull(crand.Reader, buff) | ||||
| 	if len(buff) != ret || err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	buff2 := RandByteWeakCrypto(n) | ||||
| 	for i := 0; i < n; i++ { | ||||
| 		buff[i] ^= buff2[2] | ||||
| 	} | ||||
| 	return buff | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| 	On Unix-like systems, Reader reads from /dev/urandom. | ||||
| 	On Windows systems, Reader uses the CryptGenRandom API. | ||||
| */ | ||||
| func RandByteWeakCrypto(n int) []byte { | ||||
| 	buff := make([]byte, n) | ||||
| 	ret, err := io.ReadFull(crand.Reader, buff) | ||||
| 	if len(buff) != ret || err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return buff | ||||
| } | ||||
							
								
								
									
										228
									
								
								crypto/secp256k1/secp256_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								crypto/secp256k1/secp256_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,228 @@ | ||||
| package secp256k1 | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| const TESTS = 10000 // how many tests
 | ||||
| const SigSize = 65  //64+1
 | ||||
| 
 | ||||
| func Test_Secp256_00(t *testing.T) { | ||||
| 
 | ||||
| 	var nonce []byte = RandByte(32) //going to get bitcoins stolen!
 | ||||
| 
 | ||||
| 	if len(nonce) != 32 { | ||||
| 		t.Fatal() | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| //tests for Malleability
 | ||||
| //highest bit of S must be 0; 32nd byte
 | ||||
| func CompactSigTest(sig []byte) { | ||||
| 
 | ||||
| 	var b int = int(sig[32]) | ||||
| 	if b < 0 { | ||||
| 		log.Panic() | ||||
| 	} | ||||
| 	if ((b >> 7) == 1) != ((b & 0x80) == 0x80) { | ||||
| 		log.Panic("b= %v b2= %v \n", b, b>>7) | ||||
| 	} | ||||
| 	if (b & 0x80) == 0x80 { | ||||
| 		log.Panic("b= %v b2= %v \n", b, b&0x80) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //test pubkey/private generation
 | ||||
| func Test_Secp256_01(t *testing.T) { | ||||
| 	pubkey, seckey := GenerateKeyPair() | ||||
| 	if err := VerifySeckeyValidity(seckey); err != nil { | ||||
| 		t.Fatal() | ||||
| 	} | ||||
| 	if err := VerifyPubkeyValidity(pubkey); err != nil { | ||||
| 		t.Fatal() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //test size of messages
 | ||||
| func Test_Secp256_02s(t *testing.T) { | ||||
| 	pubkey, seckey := GenerateKeyPair() | ||||
| 	msg := RandByte(32) | ||||
| 	sig, _ := Sign(msg, seckey) | ||||
| 	CompactSigTest(sig) | ||||
| 	if sig == nil { | ||||
| 		t.Fatal("Signature nil") | ||||
| 	} | ||||
| 	if len(pubkey) != 65 { | ||||
| 		t.Fail() | ||||
| 	} | ||||
| 	if len(seckey) != 32 { | ||||
| 		t.Fail() | ||||
| 	} | ||||
| 	if len(sig) != 64+1 { | ||||
| 		t.Fail() | ||||
| 	} | ||||
| 	if int(sig[64]) > 4 { | ||||
| 		t.Fail() | ||||
| 	} //should be 0 to 4
 | ||||
| } | ||||
| 
 | ||||
| //test signing message
 | ||||
| func Test_Secp256_02(t *testing.T) { | ||||
| 	pubkey1, seckey := GenerateKeyPair() | ||||
| 	msg := RandByte(32) | ||||
| 	sig, _ := Sign(msg, seckey) | ||||
| 	if sig == nil { | ||||
| 		t.Fatal("Signature nil") | ||||
| 	} | ||||
| 
 | ||||
| 	pubkey2, _ := RecoverPubkey(msg, sig) | ||||
| 	if pubkey2 == nil { | ||||
| 		t.Fatal("Recovered pubkey invalid") | ||||
| 	} | ||||
| 	if bytes.Equal(pubkey1, pubkey2) == false { | ||||
| 		t.Fatal("Recovered pubkey does not match") | ||||
| 	} | ||||
| 
 | ||||
| 	err := VerifySignature(msg, sig, pubkey1) | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Signature invalid") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //test pubkey recovery
 | ||||
| func Test_Secp256_02a(t *testing.T) { | ||||
| 	pubkey1, seckey1 := GenerateKeyPair() | ||||
| 	msg := RandByte(32) | ||||
| 	sig, _ := Sign(msg, seckey1) | ||||
| 
 | ||||
| 	if sig == nil { | ||||
| 		t.Fatal("Signature nil") | ||||
| 	} | ||||
| 	err := VerifySignature(msg, sig, pubkey1) | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Signature invalid") | ||||
| 	} | ||||
| 
 | ||||
| 	pubkey2, _ := RecoverPubkey(msg, sig) | ||||
| 	if len(pubkey1) != len(pubkey2) { | ||||
| 		t.Fatal() | ||||
| 	} | ||||
| 	for i, _ := range pubkey1 { | ||||
| 		if pubkey1[i] != pubkey2[i] { | ||||
| 			t.Fatal() | ||||
| 		} | ||||
| 	} | ||||
| 	if bytes.Equal(pubkey1, pubkey2) == false { | ||||
| 		t.Fatal() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //test random messages for the same pub/private key
 | ||||
| func Test_Secp256_03(t *testing.T) { | ||||
| 	_, seckey := GenerateKeyPair() | ||||
| 	for i := 0; i < TESTS; i++ { | ||||
| 		msg := RandByte(32) | ||||
| 		sig, _ := Sign(msg, seckey) | ||||
| 		CompactSigTest(sig) | ||||
| 
 | ||||
| 		sig[len(sig)-1] %= 4 | ||||
| 		pubkey2, _ := RecoverPubkey(msg, sig) | ||||
| 		if pubkey2 == nil { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //test random messages for different pub/private keys
 | ||||
| func Test_Secp256_04(t *testing.T) { | ||||
| 	for i := 0; i < TESTS; i++ { | ||||
| 		pubkey1, seckey := GenerateKeyPair() | ||||
| 		msg := RandByte(32) | ||||
| 		sig, _ := Sign(msg, seckey) | ||||
| 		CompactSigTest(sig) | ||||
| 
 | ||||
| 		if sig[len(sig)-1] >= 4 { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 		pubkey2, _ := RecoverPubkey(msg, sig) | ||||
| 		if pubkey2 == nil { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 		if bytes.Equal(pubkey1, pubkey2) == false { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //test random signatures against fixed messages; should fail
 | ||||
| 
 | ||||
| //crashes:
 | ||||
| //	-SIPA look at this
 | ||||
| 
 | ||||
| func randSig() []byte { | ||||
| 	sig := RandByte(65) | ||||
| 	sig[32] &= 0x70 | ||||
| 	sig[64] %= 4 | ||||
| 	return sig | ||||
| } | ||||
| 
 | ||||
| func Test_Secp256_06a_alt0(t *testing.T) { | ||||
| 	pubkey1, seckey := GenerateKeyPair() | ||||
| 	msg := RandByte(32) | ||||
| 	sig, _ := Sign(msg, seckey) | ||||
| 
 | ||||
| 	if sig == nil { | ||||
| 		t.Fail() | ||||
| 	} | ||||
| 	if len(sig) != 65 { | ||||
| 		t.Fail() | ||||
| 	} | ||||
| 	for i := 0; i < TESTS; i++ { | ||||
| 		sig = randSig() | ||||
| 		pubkey2, _ := RecoverPubkey(msg, sig) | ||||
| 
 | ||||
| 		if bytes.Equal(pubkey1, pubkey2) == true { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 
 | ||||
| 		if pubkey2 != nil && VerifySignature(msg, sig, pubkey2) != nil { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 
 | ||||
| 		if VerifySignature(msg, sig, pubkey1) == nil { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //test random messages against valid signature: should fail
 | ||||
| 
 | ||||
| func Test_Secp256_06b(t *testing.T) { | ||||
| 	pubkey1, seckey := GenerateKeyPair() | ||||
| 	msg := RandByte(32) | ||||
| 	sig, _ := Sign(msg, seckey) | ||||
| 
 | ||||
| 	fail_count := 0 | ||||
| 	for i := 0; i < TESTS; i++ { | ||||
| 		msg = RandByte(32) | ||||
| 		pubkey2, _ := RecoverPubkey(msg, sig) | ||||
| 		if bytes.Equal(pubkey1, pubkey2) == true { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 
 | ||||
| 		if pubkey2 != nil && VerifySignature(msg, sig, pubkey2) != nil { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 
 | ||||
| 		if VerifySignature(msg, sig, pubkey1) == nil { | ||||
| 			t.Fail() | ||||
| 		} | ||||
| 	} | ||||
| 	if fail_count != 0 { | ||||
| 		fmt.Printf("ERROR: Accepted signature for %v of %v random messages\n", fail_count, TESTS) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										19
									
								
								crypto/secp256k1/secp256k1/COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								crypto/secp256k1/secp256k1/COPYING
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| Copyright (c) 2013 Pieter Wuille | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
							
								
								
									
										55
									
								
								crypto/secp256k1/secp256k1/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								crypto/secp256k1/secp256k1/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| $(shell CC=$(CC) YASM=$(YASM) ./configure) | ||||
| include config.mk | ||||
| 
 | ||||
| FILES := src/*.h src/impl/*.h | ||||
| 
 | ||||
| JAVA_FILES := src/java/org_bitcoin_NativeSecp256k1.h src/java/org_bitcoin_NativeSecp256k1.c | ||||
| 
 | ||||
| OBJS := | ||||
| 
 | ||||
| ifeq ($(USE_ASM), 1) | ||||
|     OBJS := $(OBJS) obj/field_5x$(HAVE_LIMB)_asm.o | ||||
| endif | ||||
| STD="gnu99" | ||||
| 
 | ||||
| default: tests libsecp256k1.a libsecp256k1.so | ||||
| 
 | ||||
| clean: | ||||
| 	rm -rf obj/*.o bench tests *.a *.so config.mk | ||||
| 
 | ||||
| obj/field_5x52_asm.o: src/field_5x52_asm.asm | ||||
| 	$(YASM) -f elf64 -o obj/field_5x52_asm.o src/field_5x52_asm.asm | ||||
| 
 | ||||
| obj/field_5x64_asm.o: src/field_5x64_asm.asm | ||||
| 	$(YASM) -f elf64 -o obj/field_5x64_asm.o src/field_5x64_asm.asm | ||||
| 
 | ||||
| obj/secp256k1.o: $(FILES) src/secp256k1.c include/secp256k1.h | ||||
| 	$(CC) -fPIC -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) -DNDEBUG -$(OPTLEVEL) src/secp256k1.c -c -o obj/secp256k1.o | ||||
| 
 | ||||
| bench: $(FILES) src/bench.c $(OBJS) | ||||
| 	$(CC) -fPIC -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) $(CFLAGS_TEST_EXTRA) -DNDEBUG -$(OPTLEVEL) src/bench.c $(OBJS) $(LDFLAGS_EXTRA) $(LDFLAGS_TEST_EXTRA) -o bench | ||||
| 
 | ||||
| tests: $(FILES) src/tests.c $(OBJS) | ||||
| 	$(CC) -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) $(CFLAGS_TEST_EXTRA) -DVERIFY -fstack-protector-all -$(OPTLEVEL) -ggdb3 src/tests.c $(OBJS) $(LDFLAGS_EXTRA) $(LDFLAGS_TEST_EXTRA) -o tests | ||||
| 
 | ||||
| tests_fuzzer: $(FILES) src/tests_fuzzer.c obj/secp256k1.o $(OBJS) | ||||
| 	$(CC) -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) $(CFLAGS_TEST_EXTRA) -DVERIFY -fstack-protector-all -$(OPTLEVEL) -ggdb3 src/tests_fuzzer.c $(OBJS) obj/secp256k1.o $(LDFLAGS_EXTRA) $(LDFLAGS_TEST_EXTRA) -o tests_fuzzer | ||||
| 	 | ||||
| coverage: $(FILES) src/tests.c $(OBJS) | ||||
| 	rm -rf tests.gcno tests.gcda tests_cov | ||||
| 	$(CC) -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) $(CFLAGS_TEST_EXTRA) -DVERIFY --coverage -$(OPTLEVEL) -g src/tests.c $(OBJS) $(LDFLAGS_EXTRA) $(LDFLAGS_TEST_EXTRA) -o tests_cov | ||||
| 	rm -rf lcov | ||||
| 	mkdir -p lcov | ||||
| 	cd lcov; lcov --directory ../ --zerocounters | ||||
| 	cd lcov; ../tests_cov | ||||
| 	cd lcov; lcov --directory ../ --capture --output-file secp256k1.info | ||||
| 	cd lcov; genhtml -o . secp256k1.info | ||||
| 
 | ||||
| libsecp256k1.a: obj/secp256k1.o $(OBJS) | ||||
| 	$(AR) -rs $@ $(OBJS) obj/secp256k1.o | ||||
| 
 | ||||
| libsecp256k1.so: obj/secp256k1.o $(OBJS) | ||||
| 	$(CC) -std=$(STD) $(LDFLAGS_EXTRA) $(OBJS) obj/secp256k1.o -shared -o libsecp256k1.so | ||||
| 
 | ||||
| libjavasecp256k1.so: $(OBJS) obj/secp256k1.o $(JAVA_FILES) | ||||
| 	$(CC) -fPIC -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) -DNDEBUG -$(OPTLEVEL) -I. src/java/org_bitcoin_NativeSecp256k1.c $(LDFLAGS_EXTRA) $(OBJS) obj/secp256k1.o -shared -o libjavasecp256k1.so | ||||
							
								
								
									
										3
									
								
								crypto/secp256k1/secp256k1/TODO
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								crypto/secp256k1/secp256k1/TODO
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| * Unit tests for fieldelem/groupelem, including ones intended to | ||||
|   trigger fieldelem's boundary cases. | ||||
| * Complete constant-time operations for signing/keygen | ||||
							
								
								
									
										9
									
								
								crypto/secp256k1/secp256k1/config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								crypto/secp256k1/secp256k1/config.mk
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| CC=cc | ||||
| YASM=yasm | ||||
| CFLAGS_EXTRA=-DUSE_FIELD_5X52 -DUSE_FIELD_5X52_ASM -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM | ||||
| CFLAGS_TEST_EXTRA=-DENABLE_OPENSSL_TESTS | ||||
| LDFLAGS_EXTRA=-lgmp | ||||
| LDFLAGS_TEST_EXTRA=-lcrypto | ||||
| USE_ASM=1 | ||||
| HAVE_LIMB=52 | ||||
| OPTLEVEL=O2 | ||||
							
								
								
									
										175
									
								
								crypto/secp256k1/secp256k1/configure
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										175
									
								
								crypto/secp256k1/secp256k1/configure
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @ -0,0 +1,175 @@ | ||||
| #!/bin/sh | ||||
| 
 | ||||
| if test -f config.mk; then | ||||
|     exit 0 | ||||
| fi | ||||
| 
 | ||||
| if test -z "$CC"; then | ||||
|     CC=cc | ||||
| fi | ||||
| 
 | ||||
| if test -z "$YASM"; then | ||||
|     YASM=yasm | ||||
| fi | ||||
| 
 | ||||
| # test yasm | ||||
| $YASM -f elf64 -o /tmp/secp256k1-$$.o - <<EOF | ||||
| 	BITS 64 | ||||
| 	GLOBAL testyasm | ||||
| 	ALIGN 32 | ||||
| testyasm: | ||||
| 	xor r9,r9 | ||||
| EOF | ||||
| if [ "$?" = 0 ]; then | ||||
|     $CC $CFLAGS -std=c99 -x c -c - -o /tmp/secp256k1-$$-2.o 2>/dev/null <<EOF | ||||
| void __attribute__ ((sysv_abi)) testyasm(void); | ||||
| int main() { | ||||
|     testyasm(); | ||||
|     return 0; | ||||
| } | ||||
| EOF | ||||
|     $CC $CFLAGS -std=c99 /tmp/secp256k1-$$-2.o /tmp/secp256k1-$$.o -o /dev/null 2>/dev/null | ||||
|     if [ "$?" = 0 ]; then | ||||
|         HAVE_YASM=1 | ||||
|     fi | ||||
|     rm -rf /tmp/secp256k1-$$-2.o /tmp/secp256k1-$$.o | ||||
| fi | ||||
| 
 | ||||
| # test openssl | ||||
| HAVE_OPENSSL=0 | ||||
| $CC $CFLAGS -std=c99 -x c - -o /dev/null -lcrypto 2>/dev/null <<EOF | ||||
| #include <openssl/bn.h> | ||||
| int main() { | ||||
|     BN_CTX *ctx = BN_CTX_new(); | ||||
|     BN_CTX_free(ctx); | ||||
|     return 0; | ||||
| } | ||||
| EOF | ||||
| if [ "$?" = 0 ]; then | ||||
|     HAVE_OPENSSL=1 | ||||
| fi | ||||
| 
 | ||||
| # test openssl/EC | ||||
| HAVE_OPENSSL_EC=0 | ||||
| if [ "$HAVE_OPENSSL" = "1" ]; then | ||||
| $CC $CFLAGS -std=c99 -x c - -o /dev/null -lcrypto 2>/dev/null <<EOF | ||||
| #include <openssl/ec.h> | ||||
| #include <openssl/ecdsa.h> | ||||
| #include <openssl/obj_mac.h> | ||||
| int main() { | ||||
|     EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1); | ||||
|     ECDSA_sign(0, NULL, 0, NULL, NULL, eckey); | ||||
|     ECDSA_verify(0, NULL, 0, NULL, 0, eckey); | ||||
|     EC_KEY_free(eckey); | ||||
|     return 0; | ||||
| } | ||||
| EOF | ||||
| if [ "$?" = 0 ]; then | ||||
|     HAVE_OPENSSL_EC=1 | ||||
| fi | ||||
| fi | ||||
| 
 | ||||
| # test gmp | ||||
| HAVE_GMP=0 | ||||
| $CC $CFLAGS -std=c99 -x c - -o /dev/null -lgmp 2>/dev/null <<EOF | ||||
| #include <gmp.h> | ||||
| int main() { | ||||
|     mpz_t n; | ||||
|     mpz_init(n); | ||||
|     mpz_clear(n); | ||||
|     return 0; | ||||
| } | ||||
| EOF | ||||
| if [ "$?" = 0 ]; then | ||||
|     HAVE_GMP=1 | ||||
| fi | ||||
| 
 | ||||
| # test __int128 | ||||
| HAVE_INT128=0 | ||||
| $CC $CFLAGS -std=c99 -x c - -o /dev/null 2>/dev/null <<EOF | ||||
| #include <stdint.h> | ||||
| int main() { | ||||
|     __int128 x = 0; | ||||
|     return 0; | ||||
| } | ||||
| EOF | ||||
| if [ "$?" = 0 ]; then | ||||
|     HAVE_INT128=1 | ||||
| fi | ||||
| 
 | ||||
| #default limb size | ||||
| HAVE_LIMB=52 | ||||
| 
 | ||||
| for arg in "$@"; do | ||||
|     case "$arg" in | ||||
|         --no-yasm) | ||||
|             HAVE_YASM=0 | ||||
|             ;; | ||||
|         --no-gmp) | ||||
|             HAVE_GMP=0 | ||||
|             ;; | ||||
|         --no-openssl) | ||||
|             HAVE_OPENSSL=0 | ||||
| 	    ;; | ||||
| 	--use-5x64) | ||||
| 	    HAVE_LIMB=64 | ||||
|             ;; | ||||
|     esac | ||||
| done | ||||
| 
 | ||||
| LINK_OPENSSL=0 | ||||
| LINK_GMP=0 | ||||
| USE_ASM=0 | ||||
| 
 | ||||
| # select field implementation | ||||
| if [ "$HAVE_YASM" = "1" ]; then | ||||
|     CFLAGS_FIELD="-DUSE_FIELD_5X$HAVE_LIMB -DUSE_FIELD_5X${HAVE_LIMB}_ASM" | ||||
|     USE_ASM=1 | ||||
| elif [ "$HAVE_INT128" = "1" ]; then | ||||
|     CFLAGS_FIELD="-DUSE_FIELD_5X$HAVE_LIMB -DUSE_FIELD_5X${HAVE_LIMB}_INT128" | ||||
| elif [ "$HAVE_GMP" = "1" ]; then | ||||
|     CFLAGS_FIELD="-DUSE_FIELD_GMP" | ||||
|     LINK_GMP=1 | ||||
| else | ||||
|     CFLAGS_FIELD="-DUSE_FIELD_10X26" | ||||
| fi | ||||
| 
 | ||||
| # select num implementation | ||||
| if [ "$HAVE_GMP" = "1" ]; then | ||||
|     CFLAGS_NUM="-DUSE_NUM_GMP -DUSE_FIELD_INV_NUM" | ||||
|     LINK_GMP=1 | ||||
| elif [ "$HAVE_OPENSSL" =  "1" ]; then | ||||
|     CFLAGS_NUM="-DUSE_NUM_OPENSSL -DUSE_FIELD_INV_BUILTIN" | ||||
|     LINK_OPENSSL=1 | ||||
| else | ||||
|     echo "No usable num implementation found" >&2 | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| CFLAGS_EXTRA="$CFLAGS_FIELD $CFLAGS_NUM" | ||||
| LDFLAGS_EXTRA="" | ||||
| if [ "$LINK_GMP" = "1" ]; then | ||||
|     LDFLAGS_EXTRA="-lgmp" | ||||
| fi | ||||
| if [ "$LINK_OPENSSL" = "1" ]; then | ||||
|     LDFLAGS_EXTRA="-lcrypto" | ||||
| else | ||||
|     if [ "$HAVE_OPENSSL_EC" = "1" ]; then | ||||
|         LDFLAGS_TEST_EXTRA="-lcrypto" | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| CFLAGS_TEST_EXTRA="" | ||||
| if [ "$HAVE_OPENSSL_EC" = "1" ]; then | ||||
|     CFLAGS_TEST_EXTRA="-DENABLE_OPENSSL_TESTS" | ||||
| fi | ||||
| 
 | ||||
| echo "CC=$CC" > config.mk | ||||
| echo "YASM=$YASM" >>config.mk | ||||
| echo "CFLAGS_EXTRA=$CFLAGS_EXTRA" >> config.mk | ||||
| echo "CFLAGS_TEST_EXTRA=$CFLAGS_TEST_EXTRA" >> config.mk | ||||
| echo "LDFLAGS_EXTRA=$LDFLAGS_EXTRA" >> config.mk | ||||
| echo "LDFLAGS_TEST_EXTRA=$LDFLAGS_TEST_EXTRA" >> config.mk | ||||
| echo "USE_ASM=$USE_ASM" >>config.mk | ||||
| echo "HAVE_LIMB=$HAVE_LIMB" >>config.mk | ||||
| echo "OPTLEVEL=O2" >>config.mk | ||||
							
								
								
									
										121
									
								
								crypto/secp256k1/secp256k1/include/secp256k1.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								crypto/secp256k1/secp256k1/include/secp256k1.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | ||||
| #ifndef _SECP256K1_ | ||||
| #define _SECP256K1_ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /** Initialize the library. This may take some time (10-100 ms).
 | ||||
|  *  You need to call this before calling any other function. | ||||
|  *  It cannot run in parallel with any other functions, but once | ||||
|  *  secp256k1_start() returns, all other functions are thread-safe. | ||||
|  */ | ||||
| void secp256k1_start(void); | ||||
| 
 | ||||
| /** Free all memory associated with this library. After this, no
 | ||||
|  *  functions can be called anymore, except secp256k1_start() | ||||
|  */ | ||||
| void secp256k1_stop(void); | ||||
| 
 | ||||
| /** Verify an ECDSA signature.
 | ||||
|  *  Returns: 1: correct signature | ||||
|  *           0: incorrect signature | ||||
|  *          -1: invalid public key | ||||
|  *          -2: invalid signature | ||||
|  */ | ||||
| int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, | ||||
|                            const unsigned char *sig, int siglen, | ||||
|                            const unsigned char *pubkey, int pubkeylen); | ||||
| 
 | ||||
| /** Create an ECDSA signature.
 | ||||
|  *  Returns: 1: signature created | ||||
|  *           0: nonce invalid, try another one | ||||
|  *  In:      msg:    the message being signed | ||||
|  *           msglen: the length of the message being signed | ||||
|  *           seckey: pointer to a 32-byte secret key (assumed to be valid) | ||||
|  *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG) | ||||
|  *  Out:     sig:    pointer to a 72-byte array where the signature will be placed. | ||||
|  *           siglen: pointer to an int, which will be updated to the signature length (<=72). | ||||
|  */ | ||||
| int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen, | ||||
|                          unsigned char *sig, int *siglen, | ||||
|                          const unsigned char *seckey, | ||||
|                          const unsigned char *nonce); | ||||
| 
 | ||||
| /** Create a compact ECDSA signature (64 byte + recovery id).
 | ||||
|  *  Returns: 1: signature created | ||||
|  *           0: nonce invalid, try another one | ||||
|  *  In:      msg:    the message being signed | ||||
|  *           msglen: the length of the message being signed | ||||
|  *           seckey: pointer to a 32-byte secret key (assumed to be valid) | ||||
|  *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG) | ||||
|  *  Out:     sig:    pointer to a 64-byte array where the signature will be placed. | ||||
|  *           recid:  pointer to an int, which will be updated to contain the recovery id. | ||||
|  */ | ||||
| int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen, | ||||
|                                  unsigned char *sig64, | ||||
|                                  const unsigned char *seckey, | ||||
|                                  const unsigned char *nonce, | ||||
|                                  int *recid); | ||||
| 
 | ||||
| /** Recover an ECDSA public key from a compact signature.
 | ||||
|  *  Returns: 1: public key succesfully recovered (which guarantees a correct signature). | ||||
|  *           0: otherwise. | ||||
|  *  In:      msg:        the message assumed to be signed | ||||
|  *           msglen:     the length of the message | ||||
|  *           sig64:      signature as 64 byte array | ||||
|  *           compressed: whether to recover a compressed or uncompressed pubkey | ||||
|  *           recid:      the recovery id (as returned by ecdsa_sign_compact) | ||||
|  *  Out:     pubkey:     pointer to a 33 or 65 byte array to put the pubkey. | ||||
|  *           pubkeylen:  pointer to an int that will contain the pubkey length. | ||||
|  */ | ||||
| 
 | ||||
| int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, | ||||
|                                     const unsigned char *sig64, | ||||
|                                     unsigned char *pubkey, int *pubkeylen, | ||||
|                                     int compressed, int recid); | ||||
| 
 | ||||
| /** Verify an ECDSA secret key.
 | ||||
|  *  Returns: 1: secret key is valid | ||||
|  *           0: secret key is invalid | ||||
|  *  In:      seckey: pointer to a 32-byte secret key | ||||
|  */ | ||||
| int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey); | ||||
| 
 | ||||
| /** Just validate a public key.
 | ||||
|  *  Returns: 1: valid public key | ||||
|  *           0: invalid public key | ||||
|  */ | ||||
| int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen); | ||||
| 
 | ||||
| /** Compute the public key for a secret key.
 | ||||
|  *  In:     compressed: whether the computed public key should be compressed | ||||
|  *          seckey:     pointer to a 32-byte private key. | ||||
|  *  Out:    pubkey:     pointer to a 33-byte (if compressed) or 65-byte (if uncompressed) | ||||
|  *                      area to store the public key. | ||||
|  *          pubkeylen:  pointer to int that will be updated to contains the pubkey's | ||||
|  *                      length. | ||||
|  *  Returns: 1: secret was valid, public key stores | ||||
|  *           0: secret was invalid, try again. | ||||
|  */ | ||||
| int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed); | ||||
| 
 | ||||
| int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen); | ||||
| 
 | ||||
| int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, | ||||
|                                    unsigned char *privkey, int *privkeylen, | ||||
|                                    int compressed); | ||||
| 
 | ||||
| int secp256k1_ecdsa_privkey_import(unsigned char *seckey, | ||||
|                                    const unsigned char *privkey, int privkeylen); | ||||
| 
 | ||||
| int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak); | ||||
| int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); | ||||
| int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak); | ||||
| int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										64
									
								
								crypto/secp256k1/secp256k1/src/bench.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								crypto/secp256k1/secp256k1/src/bench.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "impl/num.h" | ||||
| #include "impl/field.h" | ||||
| #include "impl/group.h" | ||||
| #include "impl/ecmult.h" | ||||
| #include "impl/ecdsa.h" | ||||
| #include "impl/util.h" | ||||
| 
 | ||||
| void random_num_order(secp256k1_num_t *num) { | ||||
|     do { | ||||
|         unsigned char b32[32]; | ||||
|         secp256k1_rand256(b32); | ||||
|         secp256k1_num_set_bin(num, b32, 32); | ||||
|         if (secp256k1_num_is_zero(num)) | ||||
|             continue; | ||||
|         if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0) | ||||
|             continue; | ||||
|         break; | ||||
|     } while(1); | ||||
| } | ||||
| 
 | ||||
| int main() { | ||||
|     secp256k1_fe_start(); | ||||
|     secp256k1_ge_start(); | ||||
|     secp256k1_ecmult_start(); | ||||
| 
 | ||||
|     secp256k1_fe_t x; | ||||
|     const secp256k1_num_t *order = &secp256k1_ge_consts->order; | ||||
|     secp256k1_num_t r, s, m; | ||||
|     secp256k1_num_init(&r); | ||||
|     secp256k1_num_init(&s); | ||||
|     secp256k1_num_init(&m); | ||||
|     secp256k1_ecdsa_sig_t sig; | ||||
|     secp256k1_ecdsa_sig_init(&sig); | ||||
|     secp256k1_fe_set_hex(&x, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64); | ||||
|     int cnt = 0; | ||||
|     int good = 0; | ||||
|     for (int i=0; i<1000000; i++) { | ||||
|         random_num_order(&r); | ||||
|         random_num_order(&s); | ||||
|         random_num_order(&m); | ||||
|         secp256k1_ecdsa_sig_set_rs(&sig, &r, &s); | ||||
|         secp256k1_ge_t pubkey; secp256k1_ge_set_xo(&pubkey, &x, 1); | ||||
|         if (secp256k1_ge_is_valid(&pubkey)) { | ||||
|             cnt++; | ||||
|             good += secp256k1_ecdsa_sig_verify(&sig, &pubkey, &m); | ||||
|         } | ||||
|      } | ||||
|     printf("%i/%i\n", good, cnt); | ||||
|     secp256k1_num_free(&r); | ||||
|     secp256k1_num_free(&s); | ||||
|     secp256k1_num_free(&m); | ||||
|     secp256k1_ecdsa_sig_free(&sig); | ||||
| 
 | ||||
|     secp256k1_ecmult_stop(); | ||||
|     secp256k1_ge_stop(); | ||||
|     secp256k1_fe_stop(); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										28
									
								
								crypto/secp256k1/secp256k1/src/ecdsa.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								crypto/secp256k1/secp256k1/src/ecdsa.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_ECDSA_ | ||||
| #define _SECP256K1_ECDSA_ | ||||
| 
 | ||||
| #include "num.h" | ||||
| 
 | ||||
| typedef struct { | ||||
|     secp256k1_num_t r, s; | ||||
| } secp256k1_ecdsa_sig_t; | ||||
| 
 | ||||
| void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r); | ||||
| void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r); | ||||
| 
 | ||||
| int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); | ||||
| void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); | ||||
| int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size); | ||||
| int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a); | ||||
| int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message); | ||||
| int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid); | ||||
| int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid); | ||||
| void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s); | ||||
| int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); | ||||
| int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										19
									
								
								crypto/secp256k1/secp256k1/src/ecmult.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								crypto/secp256k1/secp256k1/src/ecmult.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_ECMULT_ | ||||
| #define _SECP256K1_ECMULT_ | ||||
| 
 | ||||
| #include "num.h" | ||||
| #include "group.h" | ||||
| 
 | ||||
| static void secp256k1_ecmult_start(void); | ||||
| static void secp256k1_ecmult_stop(void); | ||||
| 
 | ||||
| /** Multiply with the generator: R = a*G */ | ||||
| static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *a); | ||||
| /** Double multiply: R = na*A + ng*G */ | ||||
| static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										101
									
								
								crypto/secp256k1/secp256k1/src/field.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								crypto/secp256k1/secp256k1/src/field.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_ | ||||
| #define _SECP256K1_FIELD_ | ||||
| 
 | ||||
| /** Field element module.
 | ||||
|  * | ||||
|  *  Field elements can be represented in several ways, but code accessing | ||||
|  *  it (and implementations) need to take certain properaties into account: | ||||
|  *  - Each field element can be normalized or not. | ||||
|  *  - Each field element has a magnitude, which represents how far away | ||||
|  *    its representation is away from normalization. Normalized elements | ||||
|  *    always have a magnitude of 1, but a magnitude of 1 doesn't imply | ||||
|  *    normality. | ||||
|  */ | ||||
| 
 | ||||
| #if defined(USE_FIELD_GMP) | ||||
| #include "field_gmp.h" | ||||
| #elif defined(USE_FIELD_10X26) | ||||
| #include "field_10x26.h" | ||||
| #elif defined(USE_FIELD_5X52) | ||||
| #include "field_5x52.h" | ||||
| #elif defined(USE_FIELD_5X64) | ||||
| #include "field_5x64.h" | ||||
| #else | ||||
| #error "Please select field implementation" | ||||
| #endif | ||||
| 
 | ||||
| typedef struct { | ||||
|     secp256k1_num_t p; | ||||
| } secp256k1_fe_consts_t; | ||||
| 
 | ||||
| static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL; | ||||
| 
 | ||||
| /** Initialize field element precomputation data. */ | ||||
| void static secp256k1_fe_start(void); | ||||
| 
 | ||||
| /** Unload field element precomputation data. */ | ||||
| void static secp256k1_fe_stop(void); | ||||
| 
 | ||||
| /** Normalize a field element. */ | ||||
| void static secp256k1_fe_normalize(secp256k1_fe_t *r); | ||||
| 
 | ||||
| /** Set a field element equal to a small integer. Resulting field element is normalized. */ | ||||
| void static secp256k1_fe_set_int(secp256k1_fe_t *r, int a); | ||||
| 
 | ||||
| /** Verify whether a field element is zero. Requires the input to be normalized. */ | ||||
| int  static secp256k1_fe_is_zero(const secp256k1_fe_t *a); | ||||
| 
 | ||||
| /** Check the "oddness" of a field element. Requires the input to be normalized. */ | ||||
| int  static secp256k1_fe_is_odd(const secp256k1_fe_t *a); | ||||
| 
 | ||||
| /** Compare two field elements. Requires both inputs to be normalized */ | ||||
| int  static secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b); | ||||
| 
 | ||||
| /** Set a field element equal to 32-byte big endian value. Resulting field element is normalized. */ | ||||
| void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a); | ||||
| 
 | ||||
| /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ | ||||
| void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a); | ||||
| 
 | ||||
| /** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
 | ||||
|  *  as an argument. The magnitude of the output is one higher. */ | ||||
| void static secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m); | ||||
| 
 | ||||
| /** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
 | ||||
|  *  small integer. */ | ||||
| void static secp256k1_fe_mul_int(secp256k1_fe_t *r, int a); | ||||
| 
 | ||||
| /** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */ | ||||
| void static secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a); | ||||
| 
 | ||||
| /** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
 | ||||
|  *  The output magnitude is 1 (but not guaranteed to be normalized). */ | ||||
| void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b); | ||||
| 
 | ||||
| /** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
 | ||||
|  *  The output magnitude is 1 (but not guaranteed to be normalized). */ | ||||
| void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a); | ||||
| 
 | ||||
| /** Sets a field element to be the (modular) square root of another. Requires the inputs' magnitude to
 | ||||
|  *  be at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ | ||||
| void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a); | ||||
| 
 | ||||
| /** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
 | ||||
|  *  at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ | ||||
| void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a); | ||||
| 
 | ||||
| /** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */ | ||||
| void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a); | ||||
| 
 | ||||
| 
 | ||||
| /** Convert a field element to a hexadecimal string. */ | ||||
| void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a); | ||||
| 
 | ||||
| /** Convert a hexadecimal string to a field element. */ | ||||
| void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										19
									
								
								crypto/secp256k1/secp256k1/src/field_10x26.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								crypto/secp256k1/secp256k1/src/field_10x26.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_REPR_ | ||||
| #define _SECP256K1_FIELD_REPR_ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|     // X = sum(i=0..9, elem[i]*2^26) mod n
 | ||||
|     uint32_t n[10]; | ||||
| #ifdef VERIFY | ||||
|     int magnitude; | ||||
|     int normalized; | ||||
| #endif | ||||
| } secp256k1_fe_t; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										19
									
								
								crypto/secp256k1/secp256k1/src/field_5x52.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								crypto/secp256k1/secp256k1/src/field_5x52.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_REPR_ | ||||
| #define _SECP256K1_FIELD_REPR_ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|     // X = sum(i=0..4, elem[i]*2^52) mod n
 | ||||
|     uint64_t n[5]; | ||||
| #ifdef VERIFY | ||||
|     int magnitude; | ||||
|     int normalized; | ||||
| #endif | ||||
| } secp256k1_fe_t; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										463
									
								
								crypto/secp256k1/secp256k1/src/field_5x52_asm.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										463
									
								
								crypto/secp256k1/secp256k1/src/field_5x52_asm.asm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,463 @@ | ||||
| 	;; Added by Diederik Huys, March 2013 | ||||
| 	;; | ||||
| 	;; Provided public procedures: | ||||
| 	;; 	secp256k1_fe_mul_inner | ||||
| 	;; 	secp256k1_fe_sqr_inner | ||||
| 	;; | ||||
| 	;; Needed tools: YASM (http://yasm.tortall.net) | ||||
| 	;; | ||||
| 	;;  | ||||
| 
 | ||||
| 	BITS 64 | ||||
| 
 | ||||
| 	;;  Procedure ExSetMult | ||||
| 	;;  Register Layout: | ||||
| 	;;  INPUT: 	rdi	= a->n | ||||
| 	;; 	   	rsi  	= b->n | ||||
| 	;; 	   	rdx  	= r->a | ||||
| 	;;  | ||||
| 	;;  INTERNAL:	rdx:rax  = multiplication accumulator | ||||
| 	;; 		r9:r8    = c | ||||
| 	;; 		r10-r13  = t0-t3 | ||||
| 	;; 		r14	 = b.n[0] / t4 | ||||
| 	;; 		r15	 = b.n[1] / t5 | ||||
| 	;; 		rbx	 = b.n[2] / t6 | ||||
| 	;; 		rcx	 = b.n[3] / t7 | ||||
| 	;; 		rbp	 = Constant 0FFFFFFFFFFFFFh / t8 | ||||
| 	;; 		rsi	 = b.n / b.n[4] / t9 | ||||
| 
 | ||||
| 	GLOBAL secp256k1_fe_mul_inner | ||||
| 	ALIGN 32 | ||||
| secp256k1_fe_mul_inner: | ||||
| 	push rbp | ||||
| 	push rbx | ||||
| 	push r12 | ||||
| 	push r13 | ||||
| 	push r14 | ||||
| 	push r15 | ||||
| 	push rdx | ||||
| 	mov r14,[rsi+8*0]	; preload b.n[0]. This will be the case until | ||||
| 				; b.n[0] is no longer needed, then we reassign | ||||
| 				; r14 to t4 | ||||
| 	;; c=a.n[0] * b.n[0] | ||||
|    	mov rax,[rdi+0*8]	; load a.n[0] | ||||
| 	mov rbp,0FFFFFFFFFFFFFh | ||||
| 	mul r14			; rdx:rax=a.n[0]*b.n[0] | ||||
| 	mov r15,[rsi+1*8] | ||||
| 	mov r10,rbp		; load modulus into target register for t0 | ||||
| 	mov r8,rax | ||||
| 	and r10,rax		; only need lower qword of c | ||||
| 	shrd r8,rdx,52 | ||||
| 	xor r9,r9		; c < 2^64, so we ditch the HO part  | ||||
| 
 | ||||
| 	;; c+=a.n[0] * b.n[1] + a.n[1] * b.n[0] | ||||
| 	mov rax,[rdi+0*8] | ||||
| 	mul r15			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul r14			 | ||||
| 	mov r11,rbp | ||||
| 	mov rbx,[rsi+2*8] | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r11,r8 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9 | ||||
| 	 | ||||
| 	;; c+=a.n[0 1 2] * b.n[2 1 0] | ||||
| 	mov rax,[rdi+0*8] | ||||
| 	mul rbx			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul r15			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul r14 | ||||
| 	mov r12,rbp		 | ||||
| 	mov rcx,[rsi+3*8] | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r12,r8		 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=a.n[0 1 2 3] * b.n[3 2 1 0] | ||||
| 	mov rax,[rdi+0*8] | ||||
| 	mul rcx			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul rbx			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul r15			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	 | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul r14			 | ||||
| 	mov r13,rbp              | ||||
| 	mov rsi,[rsi+4*8]	; load b.n[4] and destroy pointer | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r13,r8 | ||||
| 
 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 
 | ||||
| 	;; c+=a.n[0 1 2 3 4] * b.n[4 3 2 1 0] | ||||
| 	mov rax,[rdi+0*8] | ||||
| 	mul rsi | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul rcx | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul rbx			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul r15			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+4*8] | ||||
| 	mul r14			 | ||||
| 	mov r14,rbp             ; load modulus into t4 and destroy a.n[0] | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r14,r8 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=a.n[1 2 3 4] * b.n[4 3 2 1] | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul rsi | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul rcx | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul rbx | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+4*8] | ||||
| 	mul r15 | ||||
| 	mov r15,rbp		 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	and r15,r8 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=a.n[2 3 4] * b.n[4 3 2] | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul rsi | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul rcx | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+4*8] | ||||
| 	mul rbx | ||||
| 	mov rbx,rbp		 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	and rbx,r8		 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=a.n[3 4] * b.n[4 3] | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul rsi | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,[rdi+4*8] | ||||
| 	mul rcx | ||||
| 	mov rcx,rbp		 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and rcx,r8		 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=a.n[4] * b.n[4] | ||||
| 	mov rax,[rdi+4*8] | ||||
| 	mul rsi | ||||
| 	;; mov rbp,rbp		; modulus already there! | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and rbp,r8  | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	mov rsi,r8		; load c into t9 and destroy b.n[4] | ||||
| 
 | ||||
| 	;; ******************************************************* | ||||
| common_exit_norm: | ||||
| 	mov rdi,01000003D10h	; load constant | ||||
| 
 | ||||
| 	mov rax,r15		; get t5 | ||||
| 	mul rdi | ||||
| 	add rax,r10    		; +t0 | ||||
| 	adc rdx,0 | ||||
| 	mov r10,0FFFFFFFFFFFFFh ; modulus. Sadly, we ran out of registers! | ||||
| 	mov r8,rax		; +c | ||||
| 	and r10,rax | ||||
| 	shrd r8,rdx,52 | ||||
| 	xor r9,r9 | ||||
| 
 | ||||
| 	mov rax,rbx		; get t6 | ||||
| 	mul rdi | ||||
| 	add rax,r11		; +t1 | ||||
| 	adc rdx,0 | ||||
| 	mov r11,0FFFFFFFFFFFFFh ; modulus | ||||
| 	add r8,rax		; +c | ||||
| 	adc r9,rdx | ||||
| 	and r11,r8 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9 | ||||
| 
 | ||||
| 	mov rax,rcx    		; get t7 | ||||
| 	mul rdi | ||||
| 	add rax,r12		; +t2 | ||||
| 	adc rdx,0 | ||||
| 	pop rbx			; retrieve pointer to this.n	 | ||||
| 	mov r12,0FFFFFFFFFFFFFh ; modulus | ||||
| 	add r8,rax		; +c | ||||
| 	adc r9,rdx | ||||
| 	and r12,r8 | ||||
| 	mov [rbx+2*8],r12	; mov into this.n[2] | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9 | ||||
| 	 | ||||
| 	mov rax,rbp    		; get t8 | ||||
| 	mul rdi | ||||
| 	add rax,r13    		; +t3 | ||||
| 	adc rdx,0 | ||||
| 	mov r13,0FFFFFFFFFFFFFh ; modulus | ||||
| 	add r8,rax		; +c | ||||
| 	adc r9,rdx | ||||
| 	and r13,r8 | ||||
| 	mov [rbx+3*8],r13	; -> this.n[3] | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9 | ||||
| 	 | ||||
| 	mov rax,rsi    		; get t9 | ||||
| 	mul rdi | ||||
| 	add rax,r14    		; +t4 | ||||
| 	adc rdx,0 | ||||
| 	mov r14,0FFFFFFFFFFFFh	; !!! | ||||
| 	add r8,rax		; +c | ||||
| 	adc r9,rdx | ||||
| 	and r14,r8 | ||||
| 	mov [rbx+4*8],r14	; -> this.n[4] | ||||
| 	shrd r8,r9,48		; !!! | ||||
| 	xor r9,r9 | ||||
| 	 | ||||
| 	mov rax,01000003D1h | ||||
| 	mul r8		 | ||||
| 	add rax,r10 | ||||
| 	adc rdx,0 | ||||
| 	mov r10,0FFFFFFFFFFFFFh ; modulus | ||||
| 	mov r8,rax | ||||
| 	and rax,r10 | ||||
| 	shrd r8,rdx,52 | ||||
| 	mov [rbx+0*8],rax	; -> this.n[0] | ||||
| 	add r8,r11 | ||||
| 	mov [rbx+1*8],r8	; -> this.n[1] | ||||
| 
 | ||||
| 	pop r15 | ||||
| 	pop r14 | ||||
| 	pop r13 | ||||
| 	pop r12 | ||||
| 	pop rbx | ||||
| 	pop rbp | ||||
| 	ret | ||||
| 
 | ||||
| 	 | ||||
| 	;;  PROC ExSetSquare | ||||
| 	;;  Register Layout: | ||||
| 	;;  INPUT: 	rdi	 = a.n | ||||
| 	;; 	   	rsi  	 = this.a | ||||
| 	;;  INTERNAL:	rdx:rax  = multiplication accumulator | ||||
| 	;; 		r9:r8    = c | ||||
| 	;; 		r10-r13  = t0-t3 | ||||
| 	;; 		r14	 = a.n[0] / t4 | ||||
| 	;; 		r15	 = a.n[1] / t5 | ||||
| 	;; 		rbx	 = a.n[2] / t6 | ||||
| 	;; 		rcx	 = a.n[3] / t7 | ||||
| 	;; 		rbp	 = 0FFFFFFFFFFFFFh / t8 | ||||
| 	;; 		rsi	 = a.n[4] / t9 | ||||
| 	GLOBAL secp256k1_fe_sqr_inner | ||||
| 	ALIGN 32 | ||||
| secp256k1_fe_sqr_inner: | ||||
| 	push rbp | ||||
| 	push rbx | ||||
| 	push r12 | ||||
| 	push r13 | ||||
| 	push r14 | ||||
| 	push r15 | ||||
| 	push rsi | ||||
| 	mov rbp,0FFFFFFFFFFFFFh | ||||
| 	 | ||||
| 	;; c=a.n[0] * a.n[0] | ||||
|    	mov r14,[rdi+0*8]	; r14=a.n[0] | ||||
| 	mov r10,rbp		; modulus  | ||||
| 	mov rax,r14 | ||||
| 	mul rax | ||||
| 	mov r15,[rdi+1*8]	; a.n[1] | ||||
| 	add r14,r14		; r14=2*a.n[0] | ||||
| 	mov r8,rax | ||||
| 	and r10,rax		; only need lower qword | ||||
| 	shrd r8,rdx,52 | ||||
| 	xor r9,r9 | ||||
| 
 | ||||
| 	;; c+=2*a.n[0] * a.n[1] | ||||
| 	mov rax,r14		; r14=2*a.n[0] | ||||
| 	mul r15 | ||||
| 	mov rbx,[rdi+2*8]	; rbx=a.n[2] | ||||
| 	mov r11,rbp 		; modulus | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r11,r8 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9 | ||||
| 	 | ||||
| 	;; c+=2*a.n[0]*a.n[2]+a.n[1]*a.n[1] | ||||
| 	mov rax,r14 | ||||
| 	mul rbx | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,r15 | ||||
| 	mov r12,rbp		; modulus | ||||
| 	mul rax | ||||
| 	mov rcx,[rdi+3*8]	; rcx=a.n[3] | ||||
| 	add r15,r15		; r15=a.n[1]*2 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r12,r8		; only need lower dword | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=2*a.n[0]*a.n[3]+2*a.n[1]*a.n[2] | ||||
| 	mov rax,r14 | ||||
| 	mul rcx | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,r15		; rax=2*a.n[1] | ||||
| 	mov r13,rbp		; modulus | ||||
| 	mul rbx | ||||
| 	mov rsi,[rdi+4*8]	; rsi=a.n[4] | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r13,r8 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=2*a.n[0]*a.n[4]+2*a.n[1]*a.n[3]+a.n[2]*a.n[2] | ||||
| 	mov rax,r14		; last time we need 2*a.n[0] | ||||
| 	mul rsi | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,r15 | ||||
| 	mul rcx | ||||
| 	mov r14,rbp		; modulus | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,rbx | ||||
| 	mul rax | ||||
| 	add rbx,rbx		; rcx=2*a.n[2] | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r14,r8 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=2*a.n[1]*a.n[4]+2*a.n[2]*a.n[3] | ||||
| 	mov rax,r15		; last time we need 2*a.n[1] | ||||
| 	mul rsi | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,rbx | ||||
| 	mul rcx | ||||
| 	mov r15,rbp		; modulus | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and r15,r8 | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=2*a.n[2]*a.n[4]+a.n[3]*a.n[3] | ||||
| 	mov rax,rbx		; last time we need 2*a.n[2] | ||||
| 	mul rsi | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 
 | ||||
| 	mov rax,rcx		; a.n[3] | ||||
| 	mul rax | ||||
| 	mov rbx,rbp		; modulus | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and rbx,r8		; only need lower dword | ||||
| 	lea rax,[2*rcx] | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=2*a.n[3]*a.n[4] | ||||
| 	mul rsi | ||||
| 	mov rcx,rbp		; modulus | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and rcx,r8		; only need lower dword | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	;; c+=a.n[4]*a.n[4] | ||||
| 	mov rax,rsi | ||||
| 	mul rax | ||||
| 	;; mov rbp,rbp		; modulus is already there! | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	and rbp,r8  | ||||
| 	shrd r8,r9,52 | ||||
| 	xor r9,r9		 | ||||
| 
 | ||||
| 	mov rsi,r8 | ||||
| 
 | ||||
| 	;; ******************************************************* | ||||
| 	jmp common_exit_norm | ||||
| 	end | ||||
| 
 | ||||
| 	 | ||||
							
								
								
									
										19
									
								
								crypto/secp256k1/secp256k1/src/field_5x64.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								crypto/secp256k1/secp256k1/src/field_5x64.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_REPR_ | ||||
| #define _SECP256K1_FIELD_REPR_ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|     // X = sum(i=0..4, elem[i]*2^64) mod n
 | ||||
|     uint64_t n[5]; | ||||
| #ifdef VERIFY | ||||
|     int reduced; // n[4] == 0
 | ||||
|     int normalized; // reduced and X < 2^256 - 0x100003D1
 | ||||
| #endif | ||||
| } secp256k1_fe_t; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										332
									
								
								crypto/secp256k1/secp256k1/src/field_5x64_asm.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								crypto/secp256k1/secp256k1/src/field_5x64_asm.asm
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,332 @@ | ||||
| 	;; Added by Diederik Huys, March 2013 | ||||
| 	;; | ||||
| 	;; Provided public procedures: | ||||
| 	;; 	secp256k1_fe_mul_inner | ||||
| 	;; 	secp256k1_fe_sqr_inner | ||||
| 	;; | ||||
| 	;; Needed tools: YASM (http://yasm.tortall.net) | ||||
| 	;; | ||||
| 	;;  | ||||
| 
 | ||||
| 	BITS 64 | ||||
| 
 | ||||
| COMP_LIMB EQU 000000001000003D1h | ||||
| 	 | ||||
| 	;;  Procedure ExSetMult | ||||
| 	;;  Register Layout: | ||||
| 	;;  INPUT: 	rdi	= a->n | ||||
| 	;; 	   	rsi  	= b->n | ||||
| 	;; 	   	rdx  	= r->a | ||||
| 	;;  | ||||
| 	;;  INTERNAL:	rdx:rax  = multiplication accumulator | ||||
| 	;; 		r8-r10   = c0-c2 | ||||
| 	;; 		r11-r15  = b.n[0]-b.n[4] / r3 - r7 | ||||
| 	;; 		rbx	 = r0 | ||||
| 	;; 		rcx	 = r1 | ||||
| 	;; 		rbp	 = r2 | ||||
| 	;; 	   | ||||
| 	GLOBAL secp256k1_fe_mul_inner | ||||
| 	ALIGN 32 | ||||
| secp256k1_fe_mul_inner: | ||||
| 	push rbp | ||||
| 	push rbx | ||||
| 	push r12 | ||||
| 	push r13 | ||||
| 	push r14 | ||||
| 	push r15 | ||||
| 	push rdx | ||||
| 
 | ||||
| 	mov r11,[rsi+8*0]	; preload b.n[0] | ||||
| 
 | ||||
| 	;;  step 1: mul_c2 | ||||
|    	mov rax,[rdi+0*8]	; load a.n[0] | ||||
| 	mul r11			; rdx:rax=a.n[0]*b.n[0] | ||||
| 	mov r12,[rsi+1*8]	; preload b.n[1] | ||||
| 	mov rbx,rax		; retire LO qword (r[0]) | ||||
| 	mov r8,rdx		; save overflow | ||||
| 	xor r9,r9		; overflow HO qwords | ||||
| 	xor r10,r10 | ||||
| 	 | ||||
| 	;; c+=a.n[0] * b.n[1] + a.n[1] * b.n[0] | ||||
| 	mov rax,[rdi+0*8] | ||||
| 	mul r12				 | ||||
| 	mov r13,[rsi+2*8]	; preload b.n[2] | ||||
| 	add r8,rax		; still the same :-) | ||||
| 	adc r9,rdx		;  | ||||
| 	adc r10,0		; mmm... | ||||
| 	 | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul r11			 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	adc r10,0 | ||||
| 	mov rcx,r8	; retire r[1] | ||||
| 	xor r8,r8 | ||||
| 	 | ||||
| 	;; c+=a.n[0 1 2] * b.n[2 1 0] | ||||
| 	mov rax,[rdi+0*8] | ||||
| 	mul r13			 | ||||
| 	mov r14,[rsi+3*8]	; preload b.n[3] | ||||
| 	add r9,rax | ||||
| 	adc r10,rdx | ||||
| 	adc r8,0 | ||||
| 	 | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul r12			 | ||||
| 	add r9,rax | ||||
| 	adc r10,rdx | ||||
| 	adc r8,0 | ||||
| 	 | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul r11 | ||||
| 	add r9,rax | ||||
| 	adc r10,rdx | ||||
| 	adc r8,0 | ||||
| 	mov rbp,r9		; retire r[2] | ||||
| 	xor r9,r9 | ||||
| 
 | ||||
| 	;; c+=a.n[0 1 2 3] * b.n[3 2 1 0] | ||||
| 	mov rax,[rdi+0*8] | ||||
| 	mul r14		 | ||||
| 	add r10,rax | ||||
| 	adc r8,rdx | ||||
| 	adc r9,0 | ||||
| 
 | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul r13 | ||||
| 	add r10,rax | ||||
| 	adc r8,rdx | ||||
| 	adc r9,0 | ||||
| 
 | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul r12 | ||||
| 	add r10,rax | ||||
| 	adc r8,rdx | ||||
| 	adc r9,0 | ||||
| 	 | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul r11			 | ||||
| 	add r10,rax | ||||
| 	adc r8,rdx | ||||
| 	adc r9,0 | ||||
| 	mov r11,r10		; retire r[3] | ||||
| 	xor r10,r10 | ||||
| 
 | ||||
| 	;; c+=a.n[1 2 3] * b.n[3 2 1] | ||||
| 	mov rax,[rdi+1*8] | ||||
| 	mul r14		 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	adc r10,0 | ||||
| 	 | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul r13		 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	adc r10,0 | ||||
| 	 | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul r12 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	adc r10,0 | ||||
| 	mov r12,r8		; retire r[4] | ||||
| 	xor r8,r8		 | ||||
| 
 | ||||
| 	;; c+=a.n[2 3] * b.n[3 2] | ||||
| 	mov rax,[rdi+2*8] | ||||
| 	mul r14 | ||||
| 	add r9,rax		; still the same :-) | ||||
| 	adc r10,rdx		;  | ||||
| 	adc r8,0		; mmm... | ||||
| 	 | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul r13		 | ||||
| 	add r9,rax | ||||
| 	adc r10,rdx | ||||
| 	adc r8,0 | ||||
| 	mov r13,r9		; retire r[5] | ||||
| 	xor r9,r9 | ||||
| 
 | ||||
| 	;; c+=a.n[3] * b.n[3] | ||||
| 	mov rax,[rdi+3*8] | ||||
| 	mul r14 | ||||
| 	add r10,rax | ||||
| 	adc r8,rdx | ||||
| 	 | ||||
| 	mov r14,r10 | ||||
| 	mov r15,r8 | ||||
| 	 | ||||
| 
 | ||||
| 	;; ******************************************************* | ||||
| common_exit_norm: | ||||
| 	mov rdi,COMP_LIMB | ||||
| 	mov rax,r12 | ||||
| 	mul rdi | ||||
| 	add rax,rbx | ||||
| 	adc rcx,rdx | ||||
| 	pop rbx | ||||
| 	mov [rbx],rax | ||||
| 
 | ||||
| 	mov rax,r13		; get r5 | ||||
| 	mul rdi | ||||
| 	add rax,rcx    		; +r1 | ||||
| 	adc rbp,rdx | ||||
| 	mov [rbx+1*8],rax | ||||
| 	 | ||||
| 	mov rax,r14		; get r6 | ||||
| 	mul rdi | ||||
| 	add rax,rbp    		; +r2 | ||||
| 	adc r11,rdx | ||||
| 	mov [rbx+2*8],rax | ||||
| 	 | ||||
| 	mov rax,r15		; get r7 | ||||
| 	mul rdi | ||||
| 	add rax,r11    		; +r3 | ||||
| 	adc rdx,0 | ||||
| 	mov [rbx+3*8],rax | ||||
| 	mov [rbx+4*8],rdx | ||||
| 	 | ||||
| 	pop r15 | ||||
| 	pop r14 | ||||
| 	pop r13 | ||||
| 	pop r12 | ||||
| 	pop rbx | ||||
| 	pop rbp | ||||
| 	ret | ||||
| 
 | ||||
| 	 | ||||
| 	;;  PROC ExSetSquare | ||||
| 	;;  Register Layout: | ||||
| 	;;  INPUT: 	rdi	 = a.n | ||||
| 	;; 	   	rsi  	 = this.a | ||||
| 	;;  INTERNAL:	rdx:rax  = multiplication accumulator | ||||
| 	;; 		r8-r10   = c | ||||
| 	;; 		r11-r15  = a.n[0]-a.n[4] / r3-r7 | ||||
| 	;; 		rbx	 = r0 | ||||
| 	;; 		rcx	 = r1 | ||||
| 	;; 		rbp	 = r2 | ||||
| 	GLOBAL secp256k1_fe_sqr_inner | ||||
| 	 | ||||
| 	ALIGN 32 | ||||
| secp256k1_fe_sqr_inner: | ||||
| 	push rbp | ||||
| 	push rbx | ||||
| 	push r12 | ||||
| 	push r13 | ||||
| 	push r14 | ||||
| 	push r15 | ||||
| 	push rsi | ||||
| 
 | ||||
| 	mov r11,[rdi+8*0]	; preload a.n[0] | ||||
| 	 | ||||
| 	;;  step 1: mul_c2 | ||||
|    	mov rax,r11		; load a.n[0] | ||||
| 	mul rax			; rdx:rax=a.n[0]² | ||||
| 	mov r12,[rdi+1*8]	; preload a.n[1] | ||||
| 	mov rbx,rax		; retire LO qword (r[0]) | ||||
| 	mov r8,rdx		; save overflow | ||||
| 	xor r9,r9		; overflow HO qwords | ||||
| 	xor r10,r10 | ||||
| 	 | ||||
| 	;; c+=2*a.n[0] * a.n[1] | ||||
| 	mov rax,r11		; load a.n[0] | ||||
| 	mul r12			; rdx:rax=a.n[0] * a.n[1] | ||||
| 	mov r13,[rdi+2*8]	; preload a.n[2] | ||||
| 	add rax,rax		; rdx:rax*=2 | ||||
| 	adc rdx,rdx | ||||
| 	adc r10,0 | ||||
| 	add r8,rax		; still the same :-) | ||||
| 	adc r9,rdx		 | ||||
| 	adc r10,0		; mmm... | ||||
| 	 | ||||
| 	mov rcx,r8		; retire r[1] | ||||
| 	xor r8,r8 | ||||
| 
 | ||||
| 	;; c+=2*a.n[0]*a.n[2]+a.n[1]*a.n[1] | ||||
| 	mov rax,r11		; load a.n[0] | ||||
| 	mul r13			; * a.n[2] | ||||
| 	mov r14,[rdi+3*8]	; preload a.n[3] | ||||
| 	add rax,rax		; rdx:rax*=2 | ||||
| 	adc rdx,rdx | ||||
| 	adc r8,0 | ||||
| 	add r9,rax | ||||
| 	adc r10,rdx | ||||
| 	adc r8,0 | ||||
| 
 | ||||
| 	mov rax,r12 | ||||
| 	mul rax | ||||
| 	add r9,rax | ||||
| 	adc r10,rdx | ||||
| 	adc r8,0 | ||||
| 	 | ||||
| 	 | ||||
| 	mov rbp,r9 | ||||
| 	xor r9,r9 | ||||
| 	 | ||||
| 	;; c+=2*a.n[0]*a.n[3]+2*a.n[1]*a.n[2] | ||||
| 	mov rax,r11		; load a.n[0] | ||||
| 	mul r14			; * a.n[3] | ||||
| 	add rax,rax		; rdx:rax*=2 | ||||
| 	adc rdx,rdx | ||||
| 	adc r9,0 | ||||
| 	add r10,rax | ||||
| 	adc r8,rdx | ||||
| 	adc r9,0 | ||||
| 
 | ||||
| 	mov rax,r12		; load a.n[1] | ||||
| 	mul r13			; * a.n[2] | ||||
| 	add rax,rax | ||||
| 	adc rdx,rdx | ||||
| 	adc r9,0 | ||||
| 	add r10,rax | ||||
| 	adc r8,rdx | ||||
| 	adc r9,0 | ||||
| 		 | ||||
| 	mov r11,r10 | ||||
| 	xor r10,r10 | ||||
| 
 | ||||
| 	;; c+=2*a.n[1]*a.n[3]+a.n[2]*a.n[2] | ||||
| 	mov rax,r12		; load a.n[1] | ||||
| 	mul r14			; * a.n[3] | ||||
| 	add rax,rax		; rdx:rax*=2 | ||||
| 	adc rdx,rdx | ||||
| 	adc r10,0 | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	adc r10,0 | ||||
| 
 | ||||
| 	mov rax,r13 | ||||
| 	mul rax | ||||
| 	add r8,rax | ||||
| 	adc r9,rdx | ||||
| 	adc r10,0 | ||||
| 
 | ||||
| 	mov r12,r8 | ||||
| 	xor r8,r8 | ||||
| 	;; c+=2*a.n[2]*a.n[3] | ||||
| 	mov rax,r13		; load a.n[2] | ||||
| 	mul r14			; * a.n[3] | ||||
| 	add rax,rax		; rdx:rax*=2 | ||||
| 	adc rdx,rdx | ||||
| 	adc r8,0 | ||||
| 	add r9,rax | ||||
| 	adc r10,rdx | ||||
| 	adc r8,0 | ||||
| 
 | ||||
| 	mov r13,r9 | ||||
| 	xor r9,r9 | ||||
| 
 | ||||
| 	;; c+=a.n[3]² | ||||
| 	mov rax,r14 | ||||
| 	mul rax | ||||
| 	add r10,rax | ||||
| 	adc r8,rdx | ||||
| 	 | ||||
| 	mov r14,r10 | ||||
| 	mov r15,r8 | ||||
| 	 | ||||
| 	jmp common_exit_norm | ||||
| 	end | ||||
| 
 | ||||
| 	 | ||||
							
								
								
									
										16
									
								
								crypto/secp256k1/secp256k1/src/field_gmp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								crypto/secp256k1/secp256k1/src/field_gmp.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_REPR_ | ||||
| #define _SECP256K1_FIELD_REPR_ | ||||
| 
 | ||||
| #include <gmp.h> | ||||
| 
 | ||||
| #define FIELD_LIMBS ((256 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) | ||||
| 
 | ||||
| typedef struct { | ||||
|     mp_limb_t n[FIELD_LIMBS+1]; | ||||
| } secp256k1_fe_t; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										108
									
								
								crypto/secp256k1/secp256k1/src/group.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								crypto/secp256k1/secp256k1/src/group.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_GROUP_ | ||||
| #define _SECP256K1_GROUP_ | ||||
| 
 | ||||
| #include "num.h" | ||||
| #include "field.h" | ||||
| 
 | ||||
| /** A group element of the secp256k1 curve, in affine coordinates. */ | ||||
| typedef struct { | ||||
|     secp256k1_fe_t x; | ||||
|     secp256k1_fe_t y; | ||||
|     int infinity; // whether this represents the point at infinity
 | ||||
| } secp256k1_ge_t; | ||||
| 
 | ||||
| /** A group element of the secp256k1 curve, in jacobian coordinates. */ | ||||
| typedef struct { | ||||
|     secp256k1_fe_t x; // actual X: x/z^2
 | ||||
|     secp256k1_fe_t y; // actual Y: y/z^3
 | ||||
|     secp256k1_fe_t z; | ||||
|     int infinity; // whether this represents the point at infinity
 | ||||
| } secp256k1_gej_t; | ||||
| 
 | ||||
| /** Global constants related to the group */ | ||||
| typedef struct { | ||||
|     secp256k1_num_t order; // the order of the curve (= order of its generator)
 | ||||
|     secp256k1_num_t half_order; // half the order of the curve (= order of its generator)
 | ||||
|     secp256k1_ge_t g; // the generator point
 | ||||
| 
 | ||||
|     // constants related to secp256k1's efficiently computable endomorphism
 | ||||
|     secp256k1_fe_t beta; | ||||
|     secp256k1_num_t lambda, a1b2, b1, a2; | ||||
| } secp256k1_ge_consts_t; | ||||
| 
 | ||||
| static const secp256k1_ge_consts_t *secp256k1_ge_consts = NULL; | ||||
| 
 | ||||
| /** Initialize the group module. */ | ||||
| void static secp256k1_ge_start(void); | ||||
| 
 | ||||
| /** De-initialize the group module. */ | ||||
| void static secp256k1_ge_stop(void); | ||||
| 
 | ||||
| /** Set a group element equal to the point at infinity */ | ||||
| void static secp256k1_ge_set_infinity(secp256k1_ge_t *r); | ||||
| 
 | ||||
| /** Set a group element equal to the point with given X and Y coordinates */ | ||||
| void static secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); | ||||
| 
 | ||||
| /** Set a group element (jacobian) equal to the point with given X coordinate, and given oddness for Y.
 | ||||
|     The result is not guaranteed to be valid. */ | ||||
| void static secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd); | ||||
| 
 | ||||
| /** Check whether a group element is the point at infinity. */ | ||||
| int  static secp256k1_ge_is_infinity(const secp256k1_ge_t *a); | ||||
| 
 | ||||
| /** Check whether a group element is valid (i.e., on the curve). */ | ||||
| int  static secp256k1_ge_is_valid(const secp256k1_ge_t *a); | ||||
| 
 | ||||
| void static secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a); | ||||
| 
 | ||||
| /** Get a hex representation of a point. *rlen will be overwritten with the real length. */ | ||||
| void static secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a); | ||||
| 
 | ||||
| /** Set a group element equal to another which is given in jacobian coordinates */ | ||||
| void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a); | ||||
| 
 | ||||
| 
 | ||||
| /** Set a group element (jacobian) equal to the point at infinity. */ | ||||
| void static secp256k1_gej_set_infinity(secp256k1_gej_t *r); | ||||
| 
 | ||||
| /** Set a group element (jacobian) equal to the point with given X and Y coordinates. */ | ||||
| void static secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); | ||||
| 
 | ||||
| /** Set a group element (jacobian) equal to another which is given in affine coordinates. */ | ||||
| void static secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a); | ||||
| 
 | ||||
| /** Get the X coordinate of a group element (jacobian). */ | ||||
| void static secp256k1_gej_get_x(secp256k1_fe_t *r, const secp256k1_gej_t *a); | ||||
| 
 | ||||
| /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ | ||||
| void static secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a); | ||||
| 
 | ||||
| /** Check whether a group element is the point at infinity. */ | ||||
| int  static secp256k1_gej_is_infinity(const secp256k1_gej_t *a); | ||||
| 
 | ||||
| /** Set r equal to the double of a. */ | ||||
| void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a); | ||||
| 
 | ||||
| /** Set r equal to the sum of a and b. */ | ||||
| void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b); | ||||
| 
 | ||||
| /** Set r equal to the sum of a and b (with b given in jacobian coordinates). This is more efficient
 | ||||
|     than secp256k1_gej_add. */ | ||||
| void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); | ||||
| 
 | ||||
| /** Get a hex representation of a point. *rlen will be overwritten with the real length. */ | ||||
| void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a); | ||||
| 
 | ||||
| /** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ | ||||
| void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a); | ||||
| 
 | ||||
| /** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is
 | ||||
|     not more than 256 bits). */ | ||||
| void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										309
									
								
								crypto/secp256k1/secp256k1/src/impl/ecdsa.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								crypto/secp256k1/secp256k1/src/impl/ecdsa.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,309 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_ECDSA_IMPL_H_ | ||||
| #define _SECP256K1_ECDSA_IMPL_H_ | ||||
| 
 | ||||
| #include "../num.h" | ||||
| #include "../field.h" | ||||
| #include "../group.h" | ||||
| #include "../ecmult.h" | ||||
| #include "../ecdsa.h" | ||||
| 
 | ||||
| void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r) { | ||||
|     secp256k1_num_init(&r->r); | ||||
|     secp256k1_num_init(&r->s); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r) { | ||||
|     secp256k1_num_free(&r->r); | ||||
|     secp256k1_num_free(&r->s); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) { | ||||
|     if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { | ||||
|         secp256k1_fe_t x; | ||||
|         secp256k1_fe_set_b32(&x, pub+1); | ||||
|         secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03); | ||||
|     } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { | ||||
|         secp256k1_fe_t x, y; | ||||
|         secp256k1_fe_set_b32(&x, pub+1); | ||||
|         secp256k1_fe_set_b32(&y, pub+33); | ||||
|         secp256k1_ge_set_xy(elem, &x, &y); | ||||
|         if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) | ||||
|             return 0; | ||||
|     } else { | ||||
|         return 0; | ||||
|     } | ||||
|     return secp256k1_ge_is_valid(elem); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) { | ||||
|     if (sig[0] != 0x30) return 0; | ||||
|     int lenr = sig[3]; | ||||
|     if (5+lenr >= size) return 0; | ||||
|     int lens = sig[lenr+5]; | ||||
|     if (sig[1] != lenr+lens+4) return 0; | ||||
|     if (lenr+lens+6 > size) return 0; | ||||
|     if (sig[2] != 0x02) return 0; | ||||
|     if (lenr == 0) return 0; | ||||
|     if (sig[lenr+4] != 0x02) return 0; | ||||
|     if (lens == 0) return 0; | ||||
|     secp256k1_num_set_bin(&r->r, sig+4, lenr); | ||||
|     secp256k1_num_set_bin(&r->s, sig+6+lenr, lens); | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) { | ||||
|     int lenR = (secp256k1_num_bits(&a->r) + 7)/8; | ||||
|     if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1)) | ||||
|         lenR++; | ||||
|     int lenS = (secp256k1_num_bits(&a->s) + 7)/8; | ||||
|     if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1)) | ||||
|         lenS++; | ||||
|     if (*size < 6+lenS+lenR) | ||||
|         return 0; | ||||
|     *size = 6 + lenS + lenR; | ||||
|     sig[0] = 0x30; | ||||
|     sig[1] = 4 + lenS + lenR; | ||||
|     sig[2] = 0x02; | ||||
|     sig[3] = lenR; | ||||
|     secp256k1_num_get_bin(sig+4, lenR, &a->r); | ||||
|     sig[4+lenR] = 0x02; | ||||
|     sig[5+lenR] = lenS; | ||||
|     secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s); | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { | ||||
|     const secp256k1_ge_consts_t *c = secp256k1_ge_consts; | ||||
| 
 | ||||
|     if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) | ||||
|         return 0; | ||||
|     if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) | ||||
|         return 0; | ||||
|     if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) | ||||
|         return 0; | ||||
| 
 | ||||
|     int ret = 0; | ||||
|     secp256k1_num_t sn, u1, u2; | ||||
|     secp256k1_num_init(&sn); | ||||
|     secp256k1_num_init(&u1); | ||||
|     secp256k1_num_init(&u2); | ||||
|     secp256k1_num_mod_inverse(&sn, &sig->s, &c->order); | ||||
|     secp256k1_num_mod_mul(&u1, &sn, message, &c->order); | ||||
|     secp256k1_num_mod_mul(&u2, &sn, &sig->r, &c->order); | ||||
|     secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey); | ||||
|     secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1); | ||||
|     if (!secp256k1_gej_is_infinity(&pr)) { | ||||
|         secp256k1_fe_t xr; secp256k1_gej_get_x(&xr, &pr); | ||||
|         secp256k1_fe_normalize(&xr); | ||||
|         unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr); | ||||
|         secp256k1_num_set_bin(r2, xrb, 32); | ||||
|         secp256k1_num_mod(r2, &c->order); | ||||
|         ret = 1; | ||||
|     } | ||||
|     secp256k1_num_free(&sn); | ||||
|     secp256k1_num_free(&u1); | ||||
|     secp256k1_num_free(&u2); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid) { | ||||
|     const secp256k1_ge_consts_t *c = secp256k1_ge_consts; | ||||
| 
 | ||||
|     if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) | ||||
|         return 0; | ||||
|     if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) | ||||
|         return 0; | ||||
|     if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) | ||||
|         return 0; | ||||
| 
 | ||||
|     secp256k1_num_t rx; | ||||
|     secp256k1_num_init(&rx); | ||||
|     secp256k1_num_copy(&rx, &sig->r); | ||||
|     if (recid & 2) { | ||||
|         secp256k1_num_add(&rx, &rx, &c->order); | ||||
|         if (secp256k1_num_cmp(&rx, &secp256k1_fe_consts->p) >= 0) | ||||
|             return 0; | ||||
|     } | ||||
|     unsigned char brx[32]; | ||||
|     secp256k1_num_get_bin(brx, 32, &rx); | ||||
|     secp256k1_num_free(&rx); | ||||
|     secp256k1_fe_t fx; | ||||
|     secp256k1_fe_set_b32(&fx, brx); | ||||
|     secp256k1_ge_t x; | ||||
|     secp256k1_ge_set_xo(&x, &fx, recid & 1); | ||||
|     if (!secp256k1_ge_is_valid(&x)) | ||||
|         return 0; | ||||
|     secp256k1_gej_t xj; | ||||
|     secp256k1_gej_set_ge(&xj, &x); | ||||
|     secp256k1_num_t rn, u1, u2; | ||||
|     secp256k1_num_init(&rn); | ||||
|     secp256k1_num_init(&u1); | ||||
|     secp256k1_num_init(&u2); | ||||
|     secp256k1_num_mod_inverse(&rn, &sig->r, &c->order); | ||||
|     secp256k1_num_mod_mul(&u1, &rn, message, &c->order); | ||||
|     secp256k1_num_sub(&u1, &c->order, &u1); | ||||
|     secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order); | ||||
|     secp256k1_gej_t qj; | ||||
|     secp256k1_ecmult(&qj, &xj, &u2, &u1); | ||||
|     if (secp256k1_gej_is_infinity(&qj)) | ||||
|         return 0; | ||||
|     secp256k1_ge_set_gej(pubkey, &qj); | ||||
|     secp256k1_num_free(&rn); | ||||
|     secp256k1_num_free(&u1); | ||||
|     secp256k1_num_free(&u2); | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { | ||||
|     secp256k1_num_t r2; | ||||
|     secp256k1_num_init(&r2); | ||||
|     int ret = 0; | ||||
|     ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0; | ||||
|     secp256k1_num_free(&r2); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid) { | ||||
|     const secp256k1_ge_consts_t *c = secp256k1_ge_consts; | ||||
| 
 | ||||
|     secp256k1_gej_t rp; | ||||
|     secp256k1_ecmult_gen(&rp, nonce); | ||||
|     secp256k1_ge_t r; | ||||
|     secp256k1_ge_set_gej(&r, &rp); | ||||
|     unsigned char b[32]; | ||||
|     secp256k1_fe_normalize(&r.x); | ||||
|     secp256k1_fe_normalize(&r.y); | ||||
|     secp256k1_fe_get_b32(b, &r.x); | ||||
|     secp256k1_num_set_bin(&sig->r, b, 32); | ||||
|     if (recid) | ||||
|         *recid = (secp256k1_num_cmp(&sig->r, &c->order) >= 0 ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); | ||||
|     secp256k1_num_mod(&sig->r, &c->order); | ||||
|     secp256k1_num_t n; | ||||
|     secp256k1_num_init(&n); | ||||
|     secp256k1_num_mod_mul(&n, &sig->r, seckey, &c->order); | ||||
|     secp256k1_num_add(&n, &n, message); | ||||
|     secp256k1_num_mod(&n, &c->order); | ||||
|     secp256k1_num_mod_inverse(&sig->s, nonce, &c->order); | ||||
|     secp256k1_num_mod_mul(&sig->s, &sig->s, &n, &c->order); | ||||
|     secp256k1_num_free(&n); | ||||
|     if (secp256k1_num_is_zero(&sig->s)) | ||||
|         return 0; | ||||
|     if (secp256k1_num_cmp(&sig->s, &c->half_order) > 0) { | ||||
|         secp256k1_num_sub(&sig->s, &c->order, &sig->s); | ||||
|         if (recid) | ||||
|             *recid ^= 1; | ||||
|     } | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) { | ||||
|     secp256k1_num_copy(&sig->r, r); | ||||
|     secp256k1_num_copy(&sig->s, s); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { | ||||
|     secp256k1_fe_normalize(&elem->x); | ||||
|     secp256k1_fe_normalize(&elem->y); | ||||
|     secp256k1_fe_get_b32(&pub[1], &elem->x); | ||||
|     if (compressed) { | ||||
|         *size = 33; | ||||
|         pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); | ||||
|     } else { | ||||
|         *size = 65; | ||||
|         pub[0] = 0x04; | ||||
|         secp256k1_fe_get_b32(&pub[33], &elem->y); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen) { | ||||
|     const unsigned char *end = privkey + privkeylen; | ||||
|     // sequence header
 | ||||
|     if (end < privkey+1 || *privkey != 0x30) | ||||
|         return 0; | ||||
|     privkey++; | ||||
|     // sequence length constructor
 | ||||
|     int lenb = 0; | ||||
|     if (end < privkey+1 || !(*privkey & 0x80)) | ||||
|         return 0; | ||||
|     lenb = *privkey & ~0x80; privkey++; | ||||
|     if (lenb < 1 || lenb > 2) | ||||
|         return 0; | ||||
|     if (end < privkey+lenb) | ||||
|         return 0; | ||||
|     // sequence length
 | ||||
|     int len = 0; | ||||
|     len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); | ||||
|     privkey += lenb; | ||||
|     if (end < privkey+len) | ||||
|         return 0; | ||||
|     // sequence element 0: version number (=1)
 | ||||
|     if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) | ||||
|         return 0; | ||||
|     privkey += 3; | ||||
|     // sequence element 1: octet string, up to 32 bytes
 | ||||
|     if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) | ||||
|         return 0; | ||||
|     secp256k1_num_set_bin(key, privkey+2, privkey[1]); | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed) { | ||||
|     secp256k1_gej_t rp; | ||||
|     secp256k1_ecmult_gen(&rp, key); | ||||
|     secp256k1_ge_t r; | ||||
|     secp256k1_ge_set_gej(&r, &rp); | ||||
|     if (compressed) { | ||||
|         static const unsigned char begin[] = { | ||||
|             0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 | ||||
|         }; | ||||
|         static const unsigned char middle[] = { | ||||
|             0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, | ||||
|             0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|             0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|             0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, | ||||
|             0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, | ||||
|             0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, | ||||
|             0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|             0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, | ||||
|             0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 | ||||
|         }; | ||||
|         unsigned char *ptr = privkey; | ||||
|         memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); | ||||
|         secp256k1_num_get_bin(ptr, 32, key); ptr += 32; | ||||
|         memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); | ||||
|         int pubkeylen = 0; | ||||
|         secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; | ||||
|         *privkeylen = ptr - privkey; | ||||
|     } else { | ||||
|         static const unsigned char begin[] = { | ||||
|             0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 | ||||
|         }; | ||||
|         static const unsigned char middle[] = { | ||||
|             0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, | ||||
|             0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|             0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|             0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, | ||||
|             0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, | ||||
|             0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, | ||||
|             0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, | ||||
|             0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, | ||||
|             0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|             0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, | ||||
|             0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 | ||||
|         }; | ||||
|         unsigned char *ptr = privkey; | ||||
|         memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); | ||||
|         secp256k1_num_get_bin(ptr, 32, key); ptr += 32; | ||||
|         memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); | ||||
|         int pubkeylen = 0; | ||||
|         secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; | ||||
|         *privkeylen = ptr - privkey; | ||||
|     } | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										238
									
								
								crypto/secp256k1/secp256k1/src/impl/ecmult.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								crypto/secp256k1/secp256k1/src/impl/ecmult.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,238 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_ECMULT_IMPL_H_ | ||||
| #define _SECP256K1_ECMULT_IMPL_H_ | ||||
| 
 | ||||
| #include "../num.h" | ||||
| #include "../group.h" | ||||
| #include "../ecmult.h" | ||||
| 
 | ||||
| // optimal for 128-bit and 256-bit exponents.
 | ||||
| #define WINDOW_A 5 | ||||
| 
 | ||||
| // larger numbers may result in slightly better performance, at the cost of
 | ||||
| // exponentially larger precomputed tables. WINDOW_G == 14 results in 640 KiB.
 | ||||
| #define WINDOW_G 14 | ||||
| 
 | ||||
| /** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table.
 | ||||
|  *  pre will contains the values [1*a,3*a,5*a,...,(2^(w-1)-1)*a], so it needs place for | ||||
|  *  2^(w-2) entries. | ||||
|  * | ||||
|  *  There are two versions of this function: | ||||
|  *  - secp256k1_ecmult_precomp_wnaf_gej, which operates on group elements in jacobian notation, | ||||
|  *    fast to precompute, but slower to use in later additions. | ||||
|  *  - secp256k1_ecmult_precomp_wnaf_ge, which operates on group elements in affine notations, | ||||
|  *    (much) slower to precompute, but a bit faster to use in later additions. | ||||
|  *  To compute a*P + b*G, we use the jacobian version for P, and the affine version for G, as | ||||
|  *  G is constant, so it only needs to be done once in advance. | ||||
|  */ | ||||
| void static secp256k1_ecmult_table_precomp_gej(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) { | ||||
|     pre[0] = *a; | ||||
|     secp256k1_gej_t d; secp256k1_gej_double(&d, &pre[0]); | ||||
|     for (int i=1; i<(1 << (w-2)); i++) | ||||
|         secp256k1_gej_add(&pre[i], &d, &pre[i-1]); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ecmult_table_precomp_ge(secp256k1_ge_t *pre, const secp256k1_ge_t *a, int w) { | ||||
|     pre[0] = *a; | ||||
|     secp256k1_gej_t x; secp256k1_gej_set_ge(&x, a); | ||||
|     secp256k1_gej_t d; secp256k1_gej_double(&d, &x); | ||||
|     for (int i=1; i<(1 << (w-2)); i++) { | ||||
|         secp256k1_gej_add_ge(&x, &d, &pre[i-1]); | ||||
|         secp256k1_ge_set_gej(&pre[i], &x); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /** The number of entries a table with precomputed multiples needs to have. */ | ||||
| #define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) | ||||
| 
 | ||||
| /** The following two macro retrieves a particular odd multiple from a table
 | ||||
|  *  of precomputed multiples. */ | ||||
| #define ECMULT_TABLE_GET(r,pre,n,w,neg) do { \ | ||||
|     assert(((n) & 1) == 1); \ | ||||
|     assert((n) >= -((1 << ((w)-1)) - 1)); \ | ||||
|     assert((n) <=  ((1 << ((w)-1)) - 1)); \ | ||||
|     if ((n) > 0) \ | ||||
|         *(r) = (pre)[((n)-1)/2]; \ | ||||
|     else \ | ||||
|         (neg)((r), &(pre)[(-(n)-1)/2]); \ | ||||
| } while(0) | ||||
| 
 | ||||
| #define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg) | ||||
| #define ECMULT_TABLE_GET_GE(r,pre,n,w)  ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg) | ||||
| 
 | ||||
| typedef struct { | ||||
|     secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)];    // odd multiples of the generator
 | ||||
|     secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator
 | ||||
|     secp256k1_ge_t prec[64][16]; // prec[j][i] = 16^j * (i+1) * G
 | ||||
|     secp256k1_ge_t fin; // -(sum(prec[j][0], j=0..63))
 | ||||
| } secp256k1_ecmult_consts_t; | ||||
| 
 | ||||
| static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL; | ||||
| 
 | ||||
| static void secp256k1_ecmult_start(void) { | ||||
|     if (secp256k1_ecmult_consts != NULL) | ||||
|         return; | ||||
| 
 | ||||
|     secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t)); | ||||
|     secp256k1_ecmult_consts = ret; | ||||
| 
 | ||||
|     // get the generator
 | ||||
|     const secp256k1_ge_t *g = &secp256k1_ge_consts->g; | ||||
| 
 | ||||
|     // calculate 2^128*generator
 | ||||
|     secp256k1_gej_t g_128j; secp256k1_gej_set_ge(&g_128j, g); | ||||
|     for (int i=0; i<128; i++) | ||||
|         secp256k1_gej_double(&g_128j, &g_128j); | ||||
|     secp256k1_ge_t g_128; secp256k1_ge_set_gej(&g_128, &g_128j); | ||||
| 
 | ||||
|     // precompute the tables with odd multiples
 | ||||
|     secp256k1_ecmult_table_precomp_ge(ret->pre_g, g, WINDOW_G); | ||||
|     secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128, WINDOW_G); | ||||
| 
 | ||||
|     // compute prec and fin
 | ||||
|     secp256k1_gej_t gg; secp256k1_gej_set_ge(&gg, g); | ||||
|     secp256k1_ge_t ad = *g; | ||||
|     secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn); | ||||
|     for (int j=0; j<64; j++) { | ||||
|         secp256k1_ge_set_gej(&ret->prec[j][0], &gg); | ||||
|         secp256k1_gej_add(&fn, &fn, &gg); | ||||
|         for (int i=1; i<16; i++) { | ||||
|             secp256k1_gej_add_ge(&gg, &gg, &ad); | ||||
|             secp256k1_ge_set_gej(&ret->prec[j][i], &gg); | ||||
|         } | ||||
|         ad = ret->prec[j][15]; | ||||
|     } | ||||
|     secp256k1_ge_set_gej(&ret->fin, &fn); | ||||
|     secp256k1_ge_neg(&ret->fin, &ret->fin); | ||||
| } | ||||
| 
 | ||||
| static void secp256k1_ecmult_stop(void) { | ||||
|     if (secp256k1_ecmult_consts == NULL) | ||||
|         return; | ||||
| 
 | ||||
|     secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts; | ||||
|     free(c); | ||||
|     secp256k1_ecmult_consts = NULL; | ||||
| } | ||||
| 
 | ||||
| /** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
 | ||||
|  *  with the following guarantees: | ||||
|  *  - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) | ||||
|  *  - two non-zero entries in wnaf are separated by at least w-1 zeroes. | ||||
|  *  - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where | ||||
|  *    bits is the number of bits necessary to represent the absolute value of the input. | ||||
|  */ | ||||
| static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) { | ||||
|     int ret = 0; | ||||
|     int zeroes = 0; | ||||
|     secp256k1_num_t x; | ||||
|     secp256k1_num_init(&x); | ||||
|     secp256k1_num_copy(&x, a); | ||||
|     int sign = 1; | ||||
|     if (secp256k1_num_is_neg(&x)) { | ||||
|         sign = -1; | ||||
|         secp256k1_num_negate(&x); | ||||
|     } | ||||
|     while (!secp256k1_num_is_zero(&x)) { | ||||
|         while (!secp256k1_num_is_odd(&x)) { | ||||
|             zeroes++; | ||||
|             secp256k1_num_shift(&x, 1); | ||||
|         } | ||||
|         int word = secp256k1_num_shift(&x, w); | ||||
|         while (zeroes) { | ||||
|             wnaf[ret++] = 0; | ||||
|             zeroes--; | ||||
|         } | ||||
|         if (word & (1 << (w-1))) { | ||||
|             secp256k1_num_inc(&x); | ||||
|             wnaf[ret++] = sign * (word - (1 << w)); | ||||
|         } else { | ||||
|             wnaf[ret++] = sign * word; | ||||
|         } | ||||
|         zeroes = w-1; | ||||
|     } | ||||
|     secp256k1_num_free(&x); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) { | ||||
|     secp256k1_num_t n; | ||||
|     secp256k1_num_init(&n); | ||||
|     secp256k1_num_copy(&n, gn); | ||||
|     const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; | ||||
|     secp256k1_gej_set_ge(r, &c->prec[0][secp256k1_num_shift(&n, 4)]); | ||||
|     for (int j=1; j<64; j++) | ||||
|         secp256k1_gej_add_ge(r, r, &c->prec[j][secp256k1_num_shift(&n, 4)]); | ||||
|     secp256k1_num_free(&n); | ||||
|     secp256k1_gej_add_ge(r, r, &c->fin); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) { | ||||
|     const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; | ||||
| 
 | ||||
|     secp256k1_num_t na_1, na_lam; | ||||
|     secp256k1_num_t ng_1, ng_128; | ||||
|     secp256k1_num_init(&na_1); | ||||
|     secp256k1_num_init(&na_lam); | ||||
|     secp256k1_num_init(&ng_1); | ||||
|     secp256k1_num_init(&ng_128); | ||||
| 
 | ||||
|     // split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit)
 | ||||
|     secp256k1_gej_split_exp(&na_1, &na_lam, na); | ||||
|     // split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit)
 | ||||
|     secp256k1_num_split(&ng_1, &ng_128, ng, 128); | ||||
| 
 | ||||
|     // build wnaf representation for na_1, na_lam, ng_1, ng_128
 | ||||
|     int wnaf_na_1[129];   int bits_na_1   = secp256k1_ecmult_wnaf(wnaf_na_1,   &na_1,   WINDOW_A); | ||||
|     int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A); | ||||
|     int wnaf_ng_1[129];   int bits_ng_1   = secp256k1_ecmult_wnaf(wnaf_ng_1,   &ng_1,   WINDOW_G); | ||||
|     int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G); | ||||
| 
 | ||||
|     // calculate a_lam = a*lambda
 | ||||
|     secp256k1_gej_t a_lam; secp256k1_gej_mul_lambda(&a_lam, a); | ||||
| 
 | ||||
|     // calculate odd multiples of a and a_lam
 | ||||
|     secp256k1_gej_t pre_a_1[ECMULT_TABLE_SIZE(WINDOW_A)], pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; | ||||
|     secp256k1_ecmult_table_precomp_gej(pre_a_1,   a,      WINDOW_A); | ||||
|     secp256k1_ecmult_table_precomp_gej(pre_a_lam, &a_lam, WINDOW_A); | ||||
| 
 | ||||
|     int bits = bits_na_1; | ||||
|     if (bits_na_lam > bits) bits = bits_na_lam; | ||||
|     if (bits_ng_1 > bits) bits = bits_ng_1; | ||||
|     if (bits_ng_128 > bits) bits = bits_ng_128; | ||||
| 
 | ||||
|     secp256k1_gej_set_infinity(r); | ||||
|     secp256k1_gej_t tmpj; | ||||
|     secp256k1_ge_t tmpa; | ||||
| 
 | ||||
|     for (int i=bits-1; i>=0; i--) { | ||||
|         secp256k1_gej_double(r, r); | ||||
|         int n; | ||||
|         if (i < bits_na_1 && (n = wnaf_na_1[i])) { | ||||
|             ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_1, n, WINDOW_A); | ||||
|             secp256k1_gej_add(r, r, &tmpj); | ||||
|         } | ||||
|         if (i < bits_na_lam && (n = wnaf_na_lam[i])) { | ||||
|             ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A); | ||||
|             secp256k1_gej_add(r, r, &tmpj); | ||||
|         } | ||||
|         if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { | ||||
|             ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G); | ||||
|             secp256k1_gej_add_ge(r, r, &tmpa); | ||||
|         } | ||||
|         if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { | ||||
|             ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G); | ||||
|             secp256k1_gej_add_ge(r, r, &tmpa); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     secp256k1_num_free(&na_1); | ||||
|     secp256k1_num_free(&na_lam); | ||||
|     secp256k1_num_free(&ng_1); | ||||
|     secp256k1_num_free(&ng_128); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										175
									
								
								crypto/secp256k1/secp256k1/src/impl/field.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								crypto/secp256k1/secp256k1/src/impl/field.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,175 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_IMPL_H_ | ||||
| #define _SECP256K1_FIELD_IMPL_H_ | ||||
| 
 | ||||
| #if defined(USE_FIELD_GMP) | ||||
| #include "field_gmp.h" | ||||
| #elif defined(USE_FIELD_10X26) | ||||
| #include "field_10x26.h" | ||||
| #elif defined(USE_FIELD_5X52) | ||||
| #include "field_5x52.h" | ||||
| #elif defined(USE_FIELD_5X64) | ||||
| #include "field_5x64.h" | ||||
| #else | ||||
| #error "Please select field implementation" | ||||
| #endif | ||||
| 
 | ||||
| void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) { | ||||
|     if (*rlen < 65) { | ||||
|         *rlen = 65; | ||||
|         return; | ||||
|     } | ||||
|     *rlen = 65; | ||||
|     unsigned char tmp[32]; | ||||
|     secp256k1_fe_t b = *a; | ||||
|     secp256k1_fe_normalize(&b); | ||||
|     secp256k1_fe_get_b32(tmp, &b); | ||||
|     for (int i=0; i<32; i++) { | ||||
|         static const char *c = "0123456789ABCDEF"; | ||||
|         r[2*i]   = c[(tmp[i] >> 4) & 0xF]; | ||||
|         r[2*i+1] = c[(tmp[i]) & 0xF]; | ||||
|     } | ||||
|     r[64] = 0x00; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) { | ||||
|     unsigned char tmp[32] = {}; | ||||
|     static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0, | ||||
|                                  0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|                                  0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}; | ||||
|     for (int i=0; i<32; i++) { | ||||
|         if (alen > i*2) | ||||
|             tmp[32 - alen/2 + i] = (cvt[(unsigned char)a[2*i]] << 4) + cvt[(unsigned char)a[2*i+1]]; | ||||
|     } | ||||
|     secp256k1_fe_set_b32(r, tmp); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
|     // calculate a^p, with p={15,780,1022,1023}
 | ||||
|     secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a); | ||||
|     secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a); | ||||
|     secp256k1_fe_t a6; secp256k1_fe_sqr(&a6, &a3); | ||||
|     secp256k1_fe_t a12; secp256k1_fe_sqr(&a12, &a6); | ||||
|     secp256k1_fe_t a15; secp256k1_fe_mul(&a15, &a12, &a3); | ||||
|     secp256k1_fe_t a30; secp256k1_fe_sqr(&a30, &a15); | ||||
|     secp256k1_fe_t a60; secp256k1_fe_sqr(&a60, &a30); | ||||
|     secp256k1_fe_t a120; secp256k1_fe_sqr(&a120, &a60); | ||||
|     secp256k1_fe_t a240; secp256k1_fe_sqr(&a240, &a120); | ||||
|     secp256k1_fe_t a255; secp256k1_fe_mul(&a255, &a240, &a15); | ||||
|     secp256k1_fe_t a510; secp256k1_fe_sqr(&a510, &a255); | ||||
|     secp256k1_fe_t a750; secp256k1_fe_mul(&a750, &a510, &a240); | ||||
|     secp256k1_fe_t a780; secp256k1_fe_mul(&a780, &a750, &a30); | ||||
|     secp256k1_fe_t a1020; secp256k1_fe_sqr(&a1020, &a510); | ||||
|     secp256k1_fe_t a1022; secp256k1_fe_mul(&a1022, &a1020, &a2); | ||||
|     secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1022, a); | ||||
|     secp256k1_fe_t x = a15; | ||||
|     for (int i=0; i<21; i++) { | ||||
|         for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); | ||||
|         secp256k1_fe_mul(&x, &x, &a1023); | ||||
|     } | ||||
|     for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); | ||||
|     secp256k1_fe_mul(&x, &x, &a1022); | ||||
|     for (int i=0; i<2; i++) { | ||||
|         for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); | ||||
|         secp256k1_fe_mul(&x, &x, &a1023); | ||||
|     } | ||||
|     for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); | ||||
|     secp256k1_fe_mul(r, &x, &a780); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
|     // calculate a^p, with p={45,63,1019,1023}
 | ||||
|     secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a); | ||||
|     secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a); | ||||
|     secp256k1_fe_t a4; secp256k1_fe_sqr(&a4, &a2); | ||||
|     secp256k1_fe_t a5; secp256k1_fe_mul(&a5, &a4, a); | ||||
|     secp256k1_fe_t a10; secp256k1_fe_sqr(&a10, &a5); | ||||
|     secp256k1_fe_t a11; secp256k1_fe_mul(&a11, &a10, a); | ||||
|     secp256k1_fe_t a21; secp256k1_fe_mul(&a21, &a11, &a10); | ||||
|     secp256k1_fe_t a42; secp256k1_fe_sqr(&a42, &a21); | ||||
|     secp256k1_fe_t a45; secp256k1_fe_mul(&a45, &a42, &a3); | ||||
|     secp256k1_fe_t a63; secp256k1_fe_mul(&a63, &a42, &a21); | ||||
|     secp256k1_fe_t a126; secp256k1_fe_sqr(&a126, &a63); | ||||
|     secp256k1_fe_t a252; secp256k1_fe_sqr(&a252, &a126); | ||||
|     secp256k1_fe_t a504; secp256k1_fe_sqr(&a504, &a252); | ||||
|     secp256k1_fe_t a1008; secp256k1_fe_sqr(&a1008, &a504); | ||||
|     secp256k1_fe_t a1019; secp256k1_fe_mul(&a1019, &a1008, &a11); | ||||
|     secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1019, &a4); | ||||
|     secp256k1_fe_t x = a63; | ||||
|     for (int i=0; i<21; i++) { | ||||
|         for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); | ||||
|         secp256k1_fe_mul(&x, &x, &a1023); | ||||
|     } | ||||
|     for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); | ||||
|     secp256k1_fe_mul(&x, &x, &a1019); | ||||
|     for (int i=0; i<2; i++) { | ||||
|         for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); | ||||
|         secp256k1_fe_mul(&x, &x, &a1023); | ||||
|     } | ||||
|     for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x); | ||||
|     secp256k1_fe_mul(r, &x, &a45); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
| #if defined(USE_FIELD_INV_BUILTIN) | ||||
|     secp256k1_fe_inv(r, a); | ||||
| #elif defined(USE_FIELD_INV_NUM) | ||||
|     unsigned char b[32]; | ||||
|     secp256k1_fe_t c = *a; | ||||
|     secp256k1_fe_normalize(&c); | ||||
|     secp256k1_fe_get_b32(b, &c); | ||||
|     secp256k1_num_t n;  | ||||
|     secp256k1_num_init(&n); | ||||
|     secp256k1_num_set_bin(&n, b, 32); | ||||
|     secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p); | ||||
|     secp256k1_num_get_bin(b, 32, &n); | ||||
|     secp256k1_num_free(&n); | ||||
|     secp256k1_fe_set_b32(r, b); | ||||
| #else | ||||
| #error "Please select field inverse implementation" | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_start(void) { | ||||
|     static const unsigned char secp256k1_fe_consts_p[] = { | ||||
|         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|         0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F | ||||
|     }; | ||||
|     if (secp256k1_fe_consts == NULL) { | ||||
|         secp256k1_fe_inner_start(); | ||||
|         secp256k1_fe_consts_t *ret = (secp256k1_fe_consts_t*)malloc(sizeof(secp256k1_fe_consts_t)); | ||||
|         secp256k1_num_init(&ret->p); | ||||
|         secp256k1_num_set_bin(&ret->p, secp256k1_fe_consts_p, sizeof(secp256k1_fe_consts_p)); | ||||
|         secp256k1_fe_consts = ret; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_stop(void) { | ||||
|     if (secp256k1_fe_consts != NULL) { | ||||
|         secp256k1_fe_consts_t *c = (secp256k1_fe_consts_t*)secp256k1_fe_consts; | ||||
|         secp256k1_num_free(&c->p); | ||||
|         free((void*)c); | ||||
|         secp256k1_fe_consts = NULL; | ||||
|         secp256k1_fe_inner_stop(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										487
									
								
								crypto/secp256k1/secp256k1/src/impl/field_10x26.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										487
									
								
								crypto/secp256k1/secp256k1/src/impl/field_10x26.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,487 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_REPR_IMPL_H_ | ||||
| #define _SECP256K1_FIELD_REPR_IMPL_H_ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #include "../num.h" | ||||
| #include "../field.h" | ||||
| 
 | ||||
| void static secp256k1_fe_inner_start(void) {} | ||||
| void static secp256k1_fe_inner_stop(void) {} | ||||
| 
 | ||||
| void static secp256k1_fe_normalize(secp256k1_fe_t *r) { | ||||
| //    fog("normalize in: ", r);
 | ||||
|     uint32_t c; | ||||
|     c = r->n[0]; | ||||
|     uint32_t t0 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[1]; | ||||
|     uint32_t t1 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[2]; | ||||
|     uint32_t t2 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[3]; | ||||
|     uint32_t t3 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[4]; | ||||
|     uint32_t t4 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[5]; | ||||
|     uint32_t t5 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[6]; | ||||
|     uint32_t t6 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[7]; | ||||
|     uint32_t t7 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[8]; | ||||
|     uint32_t t8 = c & 0x3FFFFFFUL; | ||||
|     c = (c >> 26) + r->n[9]; | ||||
|     uint32_t t9 = c & 0x03FFFFFUL; | ||||
|     c >>= 22; | ||||
| /*    r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
 | ||||
|     r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; | ||||
|     fog("         tm1: ", r); | ||||
|     fprintf(stderr, "out c= %08lx\n", (unsigned long)c);*/ | ||||
| 
 | ||||
|     // The following code will not modify the t's if c is initially 0.
 | ||||
|     uint32_t d = c * 0x3D1UL + t0; | ||||
|     t0 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t1 + c*0x40; | ||||
|     t1 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t2; | ||||
|     t2 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t3; | ||||
|     t3 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t4; | ||||
|     t4 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t5; | ||||
|     t5 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t6; | ||||
|     t6 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t7; | ||||
|     t7 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t8; | ||||
|     t8 = d & 0x3FFFFFFULL; | ||||
|     d = (d >> 26) + t9; | ||||
|     t9 = d & 0x03FFFFFULL; | ||||
|     assert((d >> 22) == 0); | ||||
| /*    r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
 | ||||
|     r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; | ||||
|     fog("         tm2: ", r); */ | ||||
| 
 | ||||
|     // Subtract p if result >= p
 | ||||
|     uint64_t low = ((uint64_t)t1 << 26) | t0; | ||||
|     uint64_t mask = -(int64_t)((t9 < 0x03FFFFFUL) | (t8 < 0x3FFFFFFUL) | (t7 < 0x3FFFFFFUL) | (t6 < 0x3FFFFFFUL) | (t5 < 0x3FFFFFFUL) | (t4 < 0x3FFFFFFUL) | (t3 < 0x3FFFFFFUL) | (t2 < 0x3FFFFFFUL) | (low < 0xFFFFEFFFFFC2FULL)); | ||||
|     t9 &= mask; | ||||
|     t8 &= mask; | ||||
|     t7 &= mask; | ||||
|     t6 &= mask; | ||||
|     t5 &= mask; | ||||
|     t4 &= mask; | ||||
|     t3 &= mask; | ||||
|     t2 &= mask; | ||||
|     low -= (~mask & 0xFFFFEFFFFFC2FULL); | ||||
| 
 | ||||
|     // push internal variables back
 | ||||
|     r->n[0] = low & 0x3FFFFFFUL; r->n[1] = (low >> 26) & 0x3FFFFFFUL; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; | ||||
|     r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; | ||||
| /*    fog("         out: ", r);*/ | ||||
| 
 | ||||
| #ifdef VERIFY | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { | ||||
|     r->n[0] = a; | ||||
|     r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; | ||||
| #ifdef VERIFY | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // TODO: not constant time!
 | ||||
| int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0 && a->n[4] == 0 && a->n[5] == 0 && a->n[6] == 0 && a->n[7] == 0 && a->n[8] == 0 && a->n[9] == 0); | ||||
| } | ||||
| 
 | ||||
| int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     return a->n[0] & 1; | ||||
| } | ||||
| 
 | ||||
| // TODO: not constant time!
 | ||||
| int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
|     assert(b->normalized); | ||||
| #endif | ||||
|     return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3] && a->n[4] == b->n[4] && | ||||
|             a->n[5] == b->n[5] && a->n[6] == b->n[6] && a->n[7] == b->n[7] && a->n[8] == b->n[8] && a->n[9] == b->n[9]); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { | ||||
|     r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | ||||
|     r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; | ||||
|     for (int i=0; i<32; i++) { | ||||
|         for (int j=0; j<4; j++) { | ||||
|             int limb = (8*i+2*j)/26; | ||||
|             int shift = (8*i+2*j)%26; | ||||
|             r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; | ||||
|         } | ||||
|     } | ||||
| #ifdef VERIFY | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ | ||||
| void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     for (int i=0; i<32; i++) { | ||||
|         int c = 0; | ||||
|         for (int j=0; j<4; j++) { | ||||
|             int limb = (8*i+2*j)/26; | ||||
|             int shift = (8*i+2*j)%26; | ||||
|             c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); | ||||
|         } | ||||
|         r[31-i] = c; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->magnitude <= m); | ||||
|     r->magnitude = m + 1; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     r->n[0] = 0x3FFFC2FUL * (m + 1) - a->n[0]; | ||||
|     r->n[1] = 0x3FFFFBFUL * (m + 1) - a->n[1]; | ||||
|     r->n[2] = 0x3FFFFFFUL * (m + 1) - a->n[2]; | ||||
|     r->n[3] = 0x3FFFFFFUL * (m + 1) - a->n[3]; | ||||
|     r->n[4] = 0x3FFFFFFUL * (m + 1) - a->n[4]; | ||||
|     r->n[5] = 0x3FFFFFFUL * (m + 1) - a->n[5]; | ||||
|     r->n[6] = 0x3FFFFFFUL * (m + 1) - a->n[6]; | ||||
|     r->n[7] = 0x3FFFFFFUL * (m + 1) - a->n[7]; | ||||
|     r->n[8] = 0x3FFFFFFUL * (m + 1) - a->n[8]; | ||||
|     r->n[9] = 0x03FFFFFUL * (m + 1) - a->n[9]; | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { | ||||
| #ifdef VERIFY | ||||
|     r->magnitude *= a; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     r->n[0] *= a; | ||||
|     r->n[1] *= a; | ||||
|     r->n[2] *= a; | ||||
|     r->n[3] *= a; | ||||
|     r->n[4] *= a; | ||||
|     r->n[5] *= a; | ||||
|     r->n[6] *= a; | ||||
|     r->n[7] *= a; | ||||
|     r->n[8] *= a; | ||||
|     r->n[9] *= a; | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     r->magnitude += a->magnitude; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     r->n[0] += a->n[0]; | ||||
|     r->n[1] += a->n[1]; | ||||
|     r->n[2] += a->n[2]; | ||||
|     r->n[3] += a->n[3]; | ||||
|     r->n[4] += a->n[4]; | ||||
|     r->n[5] += a->n[5]; | ||||
|     r->n[6] += a->n[6]; | ||||
|     r->n[7] += a->n[7]; | ||||
|     r->n[8] += a->n[8]; | ||||
|     r->n[9] += a->n[9]; | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_mul_inner(const uint32_t *a, const uint32_t *b, uint32_t *r) { | ||||
|     uint64_t c = (uint64_t)a[0] * b[0]; | ||||
|     uint32_t t0 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[1] + | ||||
|             (uint64_t)a[1] * b[0]; | ||||
|     uint32_t t1 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[2] + | ||||
|             (uint64_t)a[1] * b[1] + | ||||
|             (uint64_t)a[2] * b[0]; | ||||
|     uint32_t t2 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[3] + | ||||
|             (uint64_t)a[1] * b[2] + | ||||
|             (uint64_t)a[2] * b[1] + | ||||
|             (uint64_t)a[3] * b[0]; | ||||
|     uint32_t t3 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[4] + | ||||
|             (uint64_t)a[1] * b[3] + | ||||
|             (uint64_t)a[2] * b[2] + | ||||
|             (uint64_t)a[3] * b[1] + | ||||
|             (uint64_t)a[4] * b[0]; | ||||
|     uint32_t t4 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[5] + | ||||
|             (uint64_t)a[1] * b[4] + | ||||
|             (uint64_t)a[2] * b[3] + | ||||
|             (uint64_t)a[3] * b[2] + | ||||
|             (uint64_t)a[4] * b[1] + | ||||
|             (uint64_t)a[5] * b[0]; | ||||
|     uint32_t t5 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[6] + | ||||
|             (uint64_t)a[1] * b[5] + | ||||
|             (uint64_t)a[2] * b[4] + | ||||
|             (uint64_t)a[3] * b[3] + | ||||
|             (uint64_t)a[4] * b[2] + | ||||
|             (uint64_t)a[5] * b[1] + | ||||
|             (uint64_t)a[6] * b[0]; | ||||
|     uint32_t t6 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[7] + | ||||
|             (uint64_t)a[1] * b[6] + | ||||
|             (uint64_t)a[2] * b[5] + | ||||
|             (uint64_t)a[3] * b[4] + | ||||
|             (uint64_t)a[4] * b[3] + | ||||
|             (uint64_t)a[5] * b[2] + | ||||
|             (uint64_t)a[6] * b[1] + | ||||
|             (uint64_t)a[7] * b[0]; | ||||
|     uint32_t t7 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[8] + | ||||
|             (uint64_t)a[1] * b[7] + | ||||
|             (uint64_t)a[2] * b[6] + | ||||
|             (uint64_t)a[3] * b[5] + | ||||
|             (uint64_t)a[4] * b[4] + | ||||
|             (uint64_t)a[5] * b[3] + | ||||
|             (uint64_t)a[6] * b[2] + | ||||
|             (uint64_t)a[7] * b[1] + | ||||
|             (uint64_t)a[8] * b[0]; | ||||
|     uint32_t t8 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[0] * b[9] + | ||||
|             (uint64_t)a[1] * b[8] + | ||||
|             (uint64_t)a[2] * b[7] + | ||||
|             (uint64_t)a[3] * b[6] + | ||||
|             (uint64_t)a[4] * b[5] + | ||||
|             (uint64_t)a[5] * b[4] + | ||||
|             (uint64_t)a[6] * b[3] + | ||||
|             (uint64_t)a[7] * b[2] + | ||||
|             (uint64_t)a[8] * b[1] + | ||||
|             (uint64_t)a[9] * b[0]; | ||||
|     uint32_t t9 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[1] * b[9] + | ||||
|             (uint64_t)a[2] * b[8] + | ||||
|             (uint64_t)a[3] * b[7] + | ||||
|             (uint64_t)a[4] * b[6] + | ||||
|             (uint64_t)a[5] * b[5] + | ||||
|             (uint64_t)a[6] * b[4] + | ||||
|             (uint64_t)a[7] * b[3] + | ||||
|             (uint64_t)a[8] * b[2] + | ||||
|             (uint64_t)a[9] * b[1]; | ||||
|     uint32_t t10 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[2] * b[9] + | ||||
|             (uint64_t)a[3] * b[8] + | ||||
|             (uint64_t)a[4] * b[7] + | ||||
|             (uint64_t)a[5] * b[6] + | ||||
|             (uint64_t)a[6] * b[5] + | ||||
|             (uint64_t)a[7] * b[4] + | ||||
|             (uint64_t)a[8] * b[3] + | ||||
|             (uint64_t)a[9] * b[2]; | ||||
|     uint32_t t11 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[3] * b[9] + | ||||
|             (uint64_t)a[4] * b[8] + | ||||
|             (uint64_t)a[5] * b[7] + | ||||
|             (uint64_t)a[6] * b[6] + | ||||
|             (uint64_t)a[7] * b[5] + | ||||
|             (uint64_t)a[8] * b[4] + | ||||
|             (uint64_t)a[9] * b[3]; | ||||
|     uint32_t t12 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[4] * b[9] + | ||||
|             (uint64_t)a[5] * b[8] + | ||||
|             (uint64_t)a[6] * b[7] + | ||||
|             (uint64_t)a[7] * b[6] + | ||||
|             (uint64_t)a[8] * b[5] + | ||||
|             (uint64_t)a[9] * b[4]; | ||||
|     uint32_t t13 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[5] * b[9] + | ||||
|             (uint64_t)a[6] * b[8] + | ||||
|             (uint64_t)a[7] * b[7] + | ||||
|             (uint64_t)a[8] * b[6] + | ||||
|             (uint64_t)a[9] * b[5]; | ||||
|     uint32_t t14 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[6] * b[9] + | ||||
|             (uint64_t)a[7] * b[8] + | ||||
|             (uint64_t)a[8] * b[7] + | ||||
|             (uint64_t)a[9] * b[6]; | ||||
|     uint32_t t15 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[7] * b[9] + | ||||
|             (uint64_t)a[8] * b[8] + | ||||
|             (uint64_t)a[9] * b[7]; | ||||
|     uint32_t t16 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[8] * b[9] + | ||||
|             (uint64_t)a[9] * b[8]; | ||||
|     uint32_t t17 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[9] * b[9]; | ||||
|     uint32_t t18 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     uint32_t t19 = c; | ||||
| 
 | ||||
|     c = t0 + (uint64_t)t10 * 0x3D10UL; | ||||
|     t0 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t1 + (uint64_t)t10*0x400UL + (uint64_t)t11 * 0x3D10UL; | ||||
|     t1 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t2 + (uint64_t)t11*0x400UL + (uint64_t)t12 * 0x3D10UL; | ||||
|     t2 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t3 + (uint64_t)t12*0x400UL + (uint64_t)t13 * 0x3D10UL; | ||||
|     r[3] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t4 + (uint64_t)t13*0x400UL + (uint64_t)t14 * 0x3D10UL; | ||||
|     r[4] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t5 + (uint64_t)t14*0x400UL + (uint64_t)t15 * 0x3D10UL; | ||||
|     r[5] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t6 + (uint64_t)t15*0x400UL + (uint64_t)t16 * 0x3D10UL; | ||||
|     r[6] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t7 + (uint64_t)t16*0x400UL + (uint64_t)t17 * 0x3D10UL; | ||||
|     r[7] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t8 + (uint64_t)t17*0x400UL + (uint64_t)t18 * 0x3D10UL; | ||||
|     r[8] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t9 + (uint64_t)t18*0x400UL + (uint64_t)t19 * 0x1000003D10ULL; | ||||
|     r[9] = c & 0x03FFFFFUL; c = c >> 22; | ||||
|     uint64_t d = t0 + c * 0x3D1UL; | ||||
|     r[0] = d & 0x3FFFFFFUL; d = d >> 26; | ||||
|     d = d + t1 + c*0x40; | ||||
|     r[1] = d & 0x3FFFFFFUL; d = d >> 26; | ||||
|     r[2] = t2 + d; | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t *r) { | ||||
|     uint64_t c = (uint64_t)a[0] * a[0]; | ||||
|     uint32_t t0 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[1]; | ||||
|     uint32_t t1 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[2] + | ||||
|             (uint64_t)a[1] * a[1]; | ||||
|     uint32_t t2 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[3] + | ||||
|             (uint64_t)(a[1]*2) * a[2]; | ||||
|     uint32_t t3 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[4] + | ||||
|             (uint64_t)(a[1]*2) * a[3] + | ||||
|             (uint64_t)a[2] * a[2]; | ||||
|     uint32_t t4 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[5] + | ||||
|             (uint64_t)(a[1]*2) * a[4] + | ||||
|             (uint64_t)(a[2]*2) * a[3]; | ||||
|     uint32_t t5 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[6] + | ||||
|             (uint64_t)(a[1]*2) * a[5] + | ||||
|             (uint64_t)(a[2]*2) * a[4] + | ||||
|             (uint64_t)a[3] * a[3]; | ||||
|     uint32_t t6 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[7] + | ||||
|             (uint64_t)(a[1]*2) * a[6] + | ||||
|             (uint64_t)(a[2]*2) * a[5] + | ||||
|             (uint64_t)(a[3]*2) * a[4]; | ||||
|     uint32_t t7 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[8] + | ||||
|             (uint64_t)(a[1]*2) * a[7] + | ||||
|             (uint64_t)(a[2]*2) * a[6] + | ||||
|             (uint64_t)(a[3]*2) * a[5] + | ||||
|             (uint64_t)a[4] * a[4]; | ||||
|     uint32_t t8 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[0]*2) * a[9] + | ||||
|             (uint64_t)(a[1]*2) * a[8] + | ||||
|             (uint64_t)(a[2]*2) * a[7] + | ||||
|             (uint64_t)(a[3]*2) * a[6] + | ||||
|             (uint64_t)(a[4]*2) * a[5]; | ||||
|     uint32_t t9 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[1]*2) * a[9] + | ||||
|             (uint64_t)(a[2]*2) * a[8] + | ||||
|             (uint64_t)(a[3]*2) * a[7] + | ||||
|             (uint64_t)(a[4]*2) * a[6] + | ||||
|             (uint64_t)a[5] * a[5]; | ||||
|     uint32_t t10 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[2]*2) * a[9] + | ||||
|             (uint64_t)(a[3]*2) * a[8] + | ||||
|             (uint64_t)(a[4]*2) * a[7] + | ||||
|             (uint64_t)(a[5]*2) * a[6]; | ||||
|     uint32_t t11 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[3]*2) * a[9] + | ||||
|             (uint64_t)(a[4]*2) * a[8] + | ||||
|             (uint64_t)(a[5]*2) * a[7] + | ||||
|             (uint64_t)a[6] * a[6]; | ||||
|     uint32_t t12 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[4]*2) * a[9] + | ||||
|             (uint64_t)(a[5]*2) * a[8] + | ||||
|             (uint64_t)(a[6]*2) * a[7]; | ||||
|     uint32_t t13 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[5]*2) * a[9] + | ||||
|             (uint64_t)(a[6]*2) * a[8] + | ||||
|             (uint64_t)a[7] * a[7]; | ||||
|     uint32_t t14 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[6]*2) * a[9] + | ||||
|             (uint64_t)(a[7]*2) * a[8]; | ||||
|     uint32_t t15 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[7]*2) * a[9] + | ||||
|             (uint64_t)a[8] * a[8]; | ||||
|     uint32_t t16 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)(a[8]*2) * a[9]; | ||||
|     uint32_t t17 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + (uint64_t)a[9] * a[9]; | ||||
|     uint32_t t18 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     uint32_t t19 = c; | ||||
| 
 | ||||
|     c = t0 + (uint64_t)t10 * 0x3D10UL; | ||||
|     t0 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t1 + (uint64_t)t10*0x400UL + (uint64_t)t11 * 0x3D10UL; | ||||
|     t1 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t2 + (uint64_t)t11*0x400UL + (uint64_t)t12 * 0x3D10UL; | ||||
|     t2 = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t3 + (uint64_t)t12*0x400UL + (uint64_t)t13 * 0x3D10UL; | ||||
|     r[3] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t4 + (uint64_t)t13*0x400UL + (uint64_t)t14 * 0x3D10UL; | ||||
|     r[4] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t5 + (uint64_t)t14*0x400UL + (uint64_t)t15 * 0x3D10UL; | ||||
|     r[5] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t6 + (uint64_t)t15*0x400UL + (uint64_t)t16 * 0x3D10UL; | ||||
|     r[6] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t7 + (uint64_t)t16*0x400UL + (uint64_t)t17 * 0x3D10UL; | ||||
|     r[7] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t8 + (uint64_t)t17*0x400UL + (uint64_t)t18 * 0x3D10UL; | ||||
|     r[8] = c & 0x3FFFFFFUL; c = c >> 26; | ||||
|     c = c + t9 + (uint64_t)t18*0x400UL + (uint64_t)t19 * 0x1000003D10ULL; | ||||
|     r[9] = c & 0x03FFFFFUL; c = c >> 22; | ||||
|     uint64_t d = t0 + c * 0x3D1UL; | ||||
|     r[0] = d & 0x3FFFFFFUL; d = d >> 26; | ||||
|     d = d + t1 + c*0x40; | ||||
|     r[1] = d & 0x3FFFFFFUL; d = d >> 26; | ||||
|     r[2] = t2 + d; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->magnitude <= 8); | ||||
|     assert(b->magnitude <= 8); | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     secp256k1_fe_mul_inner(a->n, b->n, r->n); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->magnitude <= 8); | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     secp256k1_fe_sqr_inner(a->n, r->n); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										196
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x52.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x52.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,196 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_REPR_IMPL_H_ | ||||
| #define _SECP256K1_FIELD_REPR_IMPL_H_ | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #include "../num.h" | ||||
| #include "../field.h" | ||||
| 
 | ||||
| #if defined(USE_FIELD_5X52_ASM) | ||||
| #include "field_5x52_asm.h" | ||||
| #elif defined(USE_FIELD_5X52_INT128) | ||||
| #include "field_5x52_int128.h" | ||||
| #else | ||||
| #error "Please select field_5x52 implementation" | ||||
| #endif | ||||
| 
 | ||||
| /** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
 | ||||
|  *  represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, | ||||
|  *  each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element | ||||
|  *  is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations | ||||
|  *  accept any input with magnitude at most M, and have different rules for propagating magnitude to their | ||||
|  *  output. | ||||
|  */ | ||||
| 
 | ||||
| void static secp256k1_fe_inner_start(void) {} | ||||
| void static secp256k1_fe_inner_stop(void) {} | ||||
| 
 | ||||
| void static secp256k1_fe_normalize(secp256k1_fe_t *r) { | ||||
|     uint64_t c; | ||||
|     c = r->n[0]; | ||||
|     uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; | ||||
|     c = (c >> 52) + r->n[1]; | ||||
|     uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; | ||||
|     c = (c >> 52) + r->n[2]; | ||||
|     uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; | ||||
|     c = (c >> 52) + r->n[3]; | ||||
|     uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; | ||||
|     c = (c >> 52) + r->n[4]; | ||||
|     uint64_t t4 = c & 0x0FFFFFFFFFFFFULL; | ||||
|     c >>= 48; | ||||
| 
 | ||||
|     // The following code will not modify the t's if c is initially 0.
 | ||||
|     c = c * 0x1000003D1ULL + t0; | ||||
|     t0 = c & 0xFFFFFFFFFFFFFULL; | ||||
|     c = (c >> 52) + t1; | ||||
|     t1 = c & 0xFFFFFFFFFFFFFULL; | ||||
|     c = (c >> 52) + t2; | ||||
|     t2 = c & 0xFFFFFFFFFFFFFULL; | ||||
|     c = (c >> 52) + t3; | ||||
|     t3 = c & 0xFFFFFFFFFFFFFULL; | ||||
|     c = (c >> 52) + t4; | ||||
|     t4 = c & 0x0FFFFFFFFFFFFULL; | ||||
|     assert((c >> 48) == 0); | ||||
| 
 | ||||
|     // Subtract p if result >= p
 | ||||
|     uint64_t mask = -(int64_t)((t4 < 0xFFFFFFFFFFFFULL) | (t3 < 0xFFFFFFFFFFFFFULL) | (t2 < 0xFFFFFFFFFFFFFULL) | (t1 < 0xFFFFFFFFFFFFFULL) | (t0 < 0xFFFFEFFFFFC2FULL)); | ||||
|     t4 &= mask; | ||||
|     t3 &= mask; | ||||
|     t2 &= mask; | ||||
|     t1 &= mask; | ||||
|     t0 -= (~mask & 0xFFFFEFFFFFC2FULL); | ||||
| 
 | ||||
|     // push internal variables back
 | ||||
|     r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; | ||||
| 
 | ||||
| #ifdef VERIFY | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { | ||||
|     r->n[0] = a; | ||||
|     r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | ||||
| #ifdef VERIFY | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // TODO: not constant time!
 | ||||
| int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0 && a->n[4] == 0); | ||||
| } | ||||
| 
 | ||||
| int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     return a->n[0] & 1; | ||||
| } | ||||
| 
 | ||||
| // TODO: not constant time!
 | ||||
| int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
|     assert(b->normalized); | ||||
| #endif | ||||
|     return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3] && a->n[4] == b->n[4]); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { | ||||
|     r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | ||||
|     for (int i=0; i<32; i++) { | ||||
|         for (int j=0; j<2; j++) { | ||||
|             int limb = (8*i+4*j)/52; | ||||
|             int shift = (8*i+4*j)%52; | ||||
|             r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; | ||||
|         } | ||||
|     } | ||||
| #ifdef VERIFY | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ | ||||
| void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     for (int i=0; i<32; i++) { | ||||
|         int c = 0; | ||||
|         for (int j=0; j<2; j++) { | ||||
|             int limb = (8*i+4*j)/52; | ||||
|             int shift = (8*i+4*j)%52; | ||||
|             c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); | ||||
|         } | ||||
|         r[31-i] = c; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->magnitude <= m); | ||||
|     r->magnitude = m + 1; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     r->n[0] = 0xFFFFEFFFFFC2FULL * (m + 1) - a->n[0]; | ||||
|     r->n[1] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[1]; | ||||
|     r->n[2] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[2]; | ||||
|     r->n[3] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[3]; | ||||
|     r->n[4] = 0x0FFFFFFFFFFFFULL * (m + 1) - a->n[4]; | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { | ||||
| #ifdef VERIFY | ||||
|     r->magnitude *= a; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     r->n[0] *= a; | ||||
|     r->n[1] *= a; | ||||
|     r->n[2] *= a; | ||||
|     r->n[3] *= a; | ||||
|     r->n[4] *= a; | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     r->magnitude += a->magnitude; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     r->n[0] += a->n[0]; | ||||
|     r->n[1] += a->n[1]; | ||||
|     r->n[2] += a->n[2]; | ||||
|     r->n[3] += a->n[3]; | ||||
|     r->n[4] += a->n[4]; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->magnitude <= 8); | ||||
|     assert(b->magnitude <= 8); | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     secp256k1_fe_mul_inner(a->n, b->n, r->n); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->magnitude <= 8); | ||||
|     r->magnitude = 1; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     secp256k1_fe_sqr_inner(a->n, r->n); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										11
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x52_asm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x52_asm.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ | ||||
| #define _SECP256K1_FIELD_INNER5X52_IMPL_H_ | ||||
| 
 | ||||
| void __attribute__ ((sysv_abi)) secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r); | ||||
| void __attribute__ ((sysv_abi)) secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										105
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x52_int128.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x52_int128.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ | ||||
| #define _SECP256K1_FIELD_INNER5X52_IMPL_H_ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| void static inline secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r) { | ||||
|     __int128 c = (__int128)a[0] * b[0]; | ||||
|     uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0FFFFFFFFFFFFFE0
 | ||||
|     c = c + (__int128)a[0] * b[1] + | ||||
|             (__int128)a[1] * b[0]; | ||||
|     uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 20000000000000BF
 | ||||
|     c = c + (__int128)a[0] * b[2] + | ||||
|             (__int128)a[1] * b[1] + | ||||
|             (__int128)a[2] * b[0]; | ||||
|     uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 30000000000001A0
 | ||||
|     c = c + (__int128)a[0] * b[3] + | ||||
|             (__int128)a[1] * b[2] + | ||||
|             (__int128)a[2] * b[1] + | ||||
|             (__int128)a[3] * b[0]; | ||||
|     uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 4000000000000280
 | ||||
|     c = c + (__int128)a[0] * b[4] + | ||||
|             (__int128)a[1] * b[3] + | ||||
|             (__int128)a[2] * b[2] + | ||||
|             (__int128)a[3] * b[1] + | ||||
|             (__int128)a[4] * b[0]; | ||||
|     uint64_t t4 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 320000000000037E
 | ||||
|     c = c + (__int128)a[1] * b[4] + | ||||
|             (__int128)a[2] * b[3] + | ||||
|             (__int128)a[3] * b[2] + | ||||
|             (__int128)a[4] * b[1]; | ||||
|     uint64_t t5 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 22000000000002BE
 | ||||
|     c = c + (__int128)a[2] * b[4] + | ||||
|             (__int128)a[3] * b[3] + | ||||
|             (__int128)a[4] * b[2]; | ||||
|     uint64_t t6 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 12000000000001DE
 | ||||
|     c = c + (__int128)a[3] * b[4] + | ||||
|             (__int128)a[4] * b[3]; | ||||
|     uint64_t t7 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 02000000000000FE
 | ||||
|     c = c + (__int128)a[4] * b[4]; | ||||
|     uint64_t t8 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 001000000000001E
 | ||||
|     uint64_t t9 = c; | ||||
| 
 | ||||
|     c = t0 + (__int128)t5 * 0x1000003D10ULL; | ||||
|     t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
 | ||||
|     c = c + t1 + (__int128)t6 * 0x1000003D10ULL; | ||||
|     t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
 | ||||
|     c = c + t2 + (__int128)t7 * 0x1000003D10ULL; | ||||
|     r[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
 | ||||
|     c = c + t3 + (__int128)t8 * 0x1000003D10ULL; | ||||
|     r[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
 | ||||
|     c = c + t4 + (__int128)t9 * 0x1000003D10ULL; | ||||
|     r[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
 | ||||
|     c = t0 + (__int128)c * 0x1000003D1ULL; | ||||
|     r[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
 | ||||
|     r[1] = t1 + c; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r) { | ||||
|     __int128 c = (__int128)a[0] * a[0]; | ||||
|     uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0FFFFFFFFFFFFFE0
 | ||||
|     c = c + (__int128)(a[0]*2) * a[1]; | ||||
|     uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 20000000000000BF
 | ||||
|     c = c + (__int128)(a[0]*2) * a[2] + | ||||
|             (__int128)a[1] * a[1]; | ||||
|     uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 30000000000001A0
 | ||||
|     c = c + (__int128)(a[0]*2) * a[3] + | ||||
|             (__int128)(a[1]*2) * a[2]; | ||||
|     uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 4000000000000280
 | ||||
|     c = c + (__int128)(a[0]*2) * a[4] + | ||||
|             (__int128)(a[1]*2) * a[3] + | ||||
|             (__int128)a[2] * a[2]; | ||||
|     uint64_t t4 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 320000000000037E
 | ||||
|     c = c + (__int128)(a[1]*2) * a[4] + | ||||
|             (__int128)(a[2]*2) * a[3]; | ||||
|     uint64_t t5 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 22000000000002BE
 | ||||
|     c = c + (__int128)(a[2]*2) * a[4] + | ||||
|             (__int128)a[3] * a[3]; | ||||
|     uint64_t t6 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 12000000000001DE
 | ||||
|     c = c + (__int128)(a[3]*2) * a[4]; | ||||
|     uint64_t t7 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 02000000000000FE
 | ||||
|     c = c + (__int128)a[4] * a[4]; | ||||
|     uint64_t t8 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 001000000000001E
 | ||||
|     uint64_t t9 = c; | ||||
|     c = t0 + (__int128)t5 * 0x1000003D10ULL; | ||||
|     t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
 | ||||
|     c = c + t1 + (__int128)t6 * 0x1000003D10ULL; | ||||
|     t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
 | ||||
|     c = c + t2 + (__int128)t7 * 0x1000003D10ULL; | ||||
|     r[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
 | ||||
|     c = c + t3 + (__int128)t8 * 0x1000003D10ULL; | ||||
|     r[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
 | ||||
|     c = c + t4 + (__int128)t9 * 0x1000003D10ULL; | ||||
|     r[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
 | ||||
|     c = t0 + (__int128)c * 0x1000003D1ULL; | ||||
|     r[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
 | ||||
|     r[1] = t1 + c; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										371
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x64.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x64.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,371 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_REPR_IMPL_H_ | ||||
| #define _SECP256K1_FIELD_REPR_IMPL_H_ | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #include "../num.h" | ||||
| #include "../field.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include "field_5x64_asm.h" | ||||
| 
 | ||||
| /** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
 | ||||
|  *  represented as 4 uint64_t's in base 2^64, and one overflow uint64_t. | ||||
|  */ | ||||
| 
 | ||||
| #define FULL_LIMB (0xFFFFFFFFFFFFFFFFULL) | ||||
| #define LAST_LIMB (0xFFFFFFFEFFFFFC2FULL) | ||||
| #define COMP_LIMB (0x00000001000003D1ULL) | ||||
| 
 | ||||
| void static secp256k1_fe_inner_start(void) {} | ||||
| void static secp256k1_fe_inner_stop(void) {} | ||||
| 
 | ||||
| void static secp256k1_fe_reduce(secp256k1_fe_t *r) { | ||||
|     unsigned __int128 c = (unsigned __int128)r->n[4] * COMP_LIMB + r->n[0]; | ||||
|     uint64_t n0 = c; | ||||
|     c = (c >> 64) + r->n[1]; | ||||
|     uint64_t n1 = c; | ||||
|     c = (c >> 64) + r->n[2]; | ||||
|     r->n[2] = c; | ||||
|     c = (c >> 64) + r->n[3]; | ||||
|     r->n[3] = c; | ||||
|     c = (c >> 64) * COMP_LIMB + n0; | ||||
|     r->n[0] = c; | ||||
|     r->n[1] = n1 + (c >> 64); | ||||
|     assert(r->n[1] >= n1); | ||||
|     r->n[4] = 0; | ||||
| #ifdef VERIFY | ||||
|     r->reduced = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_normalize(secp256k1_fe_t *r) { | ||||
|     secp256k1_fe_reduce(r); | ||||
| 
 | ||||
|     // Subtract p if result >= p
 | ||||
|     uint64_t mask = -(int64_t)((r->n[0] < LAST_LIMB) | (r->n[1] != ~0ULL) | (r->n[2] != ~0ULL) | (r->n[3] != ~0ULL)); | ||||
|     r->n[0] -= (~mask & LAST_LIMB); | ||||
|     r->n[1] &= mask; | ||||
|     r->n[2] &= mask; | ||||
|     r->n[3] &= mask; | ||||
|     assert(r->n[4] == 0); | ||||
| 
 | ||||
| #ifdef VERIFY | ||||
|     r->normalized = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { | ||||
|     r->n[0] = a; | ||||
|     r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | ||||
| 
 | ||||
| #ifdef VERIFY | ||||
|     r->reduced = 1; | ||||
|     r->normalized = 1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // TODO: not constant time!
 | ||||
| int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0); | ||||
| } | ||||
| 
 | ||||
| int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     return a->n[0] & 1; | ||||
| } | ||||
| 
 | ||||
| // TODO: not constant time!
 | ||||
| int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
|     assert(b->normalized); | ||||
| #endif | ||||
|     return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3]); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { | ||||
|     r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | ||||
|     for (int i=0; i<32; i++) { | ||||
|         r->n[i/8] |= (uint64_t)a[31-i] << (i&7)*8; | ||||
|     } | ||||
| #ifdef VERIFY | ||||
|     r->reduced = 1; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ | ||||
| void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     assert(a->normalized); | ||||
| #endif | ||||
|     for (int i=0; i<32; i++) { | ||||
|         r[31-i] = a->n[i/8] >> ((i&7)*8); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *ac, int m) { | ||||
|     secp256k1_fe_t a = *ac; | ||||
|     secp256k1_fe_reduce(&a); | ||||
|     unsigned __int128 c = (unsigned __int128)(~a.n[0]) + LAST_LIMB + 1; | ||||
|     r->n[0] = c; | ||||
|     c = (c >> 64) + (~a.n[1]) + FULL_LIMB; | ||||
|     r->n[1] = c; | ||||
|     c = (c >> 64) + (~a.n[2]) + FULL_LIMB; | ||||
|     r->n[2] = c; | ||||
|     c = (c >> 64) + (~a.n[3]) + FULL_LIMB; | ||||
|     r->n[3] = c; | ||||
|     r->n[4] = 0; | ||||
| #ifdef VERIFY | ||||
|     r->reduced = 1; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { | ||||
| #ifdef VERIFY | ||||
|     r->reduced = 0; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     unsigned __int128 c = (unsigned __int128)r->n[0] * a; | ||||
|     r->n[0] = c; | ||||
|     c = (c >> 64) + (unsigned __int128)r->n[1] * a; | ||||
|     r->n[1] = c; | ||||
|     c = (c >> 64) + (unsigned __int128)r->n[2] * a; | ||||
|     r->n[2] = c; | ||||
|     c = (c >> 64) + (unsigned __int128)r->n[3] * a; | ||||
|     r->n[3] = c; | ||||
|     c = (c >> 64) + (unsigned __int128)r->n[4] * a; | ||||
|     r->n[4] = c; | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
| #ifdef VERIFY | ||||
|     r->reduced = 0; | ||||
|     r->normalized = 0; | ||||
| #endif | ||||
|     unsigned __int128 c = (unsigned __int128)r->n[0] + a->n[0]; | ||||
|     r->n[0] = c; | ||||
|     c = (unsigned __int128)r->n[1] + a->n[1] + (c >> 64); | ||||
|     r->n[1] = c; | ||||
|     c = (unsigned __int128)r->n[2] + a->n[2] + (c >> 64); | ||||
|     r->n[2] = c; | ||||
|     c = (unsigned __int128)r->n[3] + a->n[3] + (c >> 64); | ||||
|     r->n[3] = c; | ||||
|     c = (unsigned __int128)r->n[4] + a->n[4] + (c >> 64); | ||||
|     r->n[4] = c; | ||||
|     assert((c >> 64) == 0); | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| #define muladd_c3(a,b,c0,c1,c2) { \ | ||||
|     unsigned __int128 q1 = ((unsigned __int128)(a)) * (b) + (c0); \ | ||||
|     (c0) = q1; \ | ||||
|     unsigned __int128 q2 = (q1 >> 64) + (c1) + (((unsigned __int128)(c2)) << 64); \ | ||||
|     (c1) = q2; \ | ||||
|     (c2) = q2 >> 64; \ | ||||
| } | ||||
| 
 | ||||
| #define sqradd_c3(a,c0,c1,c2) muladd_c3(a,a,c0,c1,c2) | ||||
| 
 | ||||
| /*#define muladd_c3(a,b,c0,c1,c2) { \
 | ||||
|     unsigned __int128 q = (unsigned __int128)(a) * (b) + (c0); \ | ||||
|     (c0) = q; \ | ||||
|     (c1) += (q >> 64); \ | ||||
|     (c2) += ((c1) < (q >> 64))?1:0; \ | ||||
| }*/ | ||||
| 
 | ||||
| #define muladd2_c3(a,b,c0,c1,c2) { \ | ||||
|     unsigned __int128 q = (unsigned __int128)(a) * (b); \ | ||||
|     uint64_t t1 = (q >> 64); \ | ||||
|     uint64_t t0 = q; \ | ||||
|     uint64_t t2 = t1+t1; (c2) += (t2<t1)?1:0; \ | ||||
|     t1 = t0+t0; t2 += (t1<t0)?1:0; \ | ||||
|     (c0) += t1; t2 += ((c0)<t1)?1:0; \ | ||||
|     (c1) += t2; (c2) += ((c1)<t2)?1:0; \ | ||||
| } | ||||
| 
 | ||||
| /*#define muladd2_c3(a,b,c0,c1,c2) { \
 | ||||
|     muladd_c3(a,b,c0,c1,c2); \ | ||||
|     muladd_c3(a,b,c0,c1,c2); \ | ||||
| }*/ | ||||
| #else | ||||
| 
 | ||||
| #define muladd_c3(a,b,c0,c1,c2) {       \ | ||||
|         register uint64_t t1, t2;       \ | ||||
|         asm ("mulq %3"                  \ | ||||
|                 : "=a"(t1),"=d"(t2)     \ | ||||
|                 : "a"(a),"m"(b)         \ | ||||
|                 : "cc");                \ | ||||
|         asm ("addq %2,%0; adcq %3,%1"   \ | ||||
|                 : "+r"(c0),"+d"(t2)     \ | ||||
|                 : "a"(t1),"g"(0)        \ | ||||
|                 : "cc");                \ | ||||
|         asm ("addq %2,%0; adcq %3,%1"   \ | ||||
|                 : "+r"(c1),"+r"(c2)     \ | ||||
|                 : "d"(t2),"g"(0)        \ | ||||
|                 : "cc");                \ | ||||
|         } | ||||
| 
 | ||||
| #define sqradd_c3(a,c0,c1,c2) {         \ | ||||
|         register uint64_t t1, t2;       \ | ||||
|         asm ("mulq %2"                  \ | ||||
|                 : "=a"(t1),"=d"(t2)     \ | ||||
|                 : "a"(a)                \ | ||||
|                 : "cc");                \ | ||||
|         asm ("addq %2,%0; adcq %3,%1"   \ | ||||
|                 : "+r"(c0),"+d"(t2)     \ | ||||
|                 : "a"(t1),"g"(0)        \ | ||||
|                 : "cc");                \ | ||||
|         asm ("addq %2,%0; adcq %3,%1"   \ | ||||
|                 : "+r"(c1),"+r"(c2)     \ | ||||
|                 : "d"(t2),"g"(0)        \ | ||||
|                 : "cc");                \ | ||||
|         } | ||||
| 
 | ||||
| #define muladd2_c3(a,b,c0,c1,c2) {      \ | ||||
|         register uint64_t t1, t2;       \ | ||||
|         asm ("mulq %3"                  \ | ||||
|                 : "=a"(t1),"=d"(t2)     \ | ||||
|                 : "a"(a),"m"(b)         \ | ||||
|                 : "cc");                \ | ||||
|         asm ("addq %0,%0; adcq %2,%1"   \ | ||||
|                 : "+d"(t2),"+r"(c2)     \ | ||||
|                 : "g"(0)                \ | ||||
|                 : "cc");                \ | ||||
|         asm ("addq %0,%0; adcq %2,%1"   \ | ||||
|                 : "+a"(t1),"+d"(t2)     \ | ||||
|                 : "g"(0)                \ | ||||
|                 : "cc");                \ | ||||
|         asm ("addq %2,%0; adcq %3,%1"   \ | ||||
|                 : "+r"(c0),"+d"(t2)     \ | ||||
|                 : "a"(t1),"g"(0)        \ | ||||
|                 : "cc");                \ | ||||
|         asm ("addq %2,%0; adcq %3,%1"   \ | ||||
|                 : "+r"(c1),"+r"(c2)     \ | ||||
|                 : "d"(t2),"g"(0)        \ | ||||
|                 : "cc");                \ | ||||
|         } | ||||
| #endif | ||||
| 
 | ||||
| #define mul_c2(a,b,c0,c1) { \ | ||||
|     unsigned __int128 q = (unsigned __int128)(a) * (b); \ | ||||
|     (c0) = q; \ | ||||
|     (c1) = (q >> 64); \ | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *ac, const secp256k1_fe_t *bc) { | ||||
| 
 | ||||
|     secp256k1_fe_t a = *ac, b = *bc; | ||||
|     secp256k1_fe_reduce(&a); | ||||
|     secp256k1_fe_reduce(&b); | ||||
| 
 | ||||
| #ifdef USE_FIELD_5X64_ASM | ||||
|     secp256k1_fe_mul_inner((&a)->n,(&b)->n,r->n); | ||||
| #else | ||||
|     uint64_t c1,c2,c3; | ||||
|     c3=0; | ||||
|     mul_c2(a.n[0], b.n[0], c1, c2); | ||||
|     uint64_t r0 = c1; c1 = 0; | ||||
|     muladd_c3(a.n[0], b.n[1], c2, c3, c1); | ||||
|     muladd_c3(a.n[1], b.n[0], c2, c3, c1); | ||||
|     uint64_t r1 = c2; c2 = 0; | ||||
|     muladd_c3(a.n[2], b.n[0], c3, c1, c2); | ||||
|     muladd_c3(a.n[1], b.n[1], c3, c1, c2); | ||||
|     muladd_c3(a.n[0], b.n[2], c3, c1, c2); | ||||
|     uint64_t r2 = c3; c3 = 0; | ||||
|     muladd_c3(a.n[0], b.n[3], c1, c2, c3); | ||||
|     muladd_c3(a.n[1], b.n[2], c1, c2, c3); | ||||
|     muladd_c3(a.n[2], b.n[1], c1, c2, c3); | ||||
|     muladd_c3(a.n[3], b.n[0], c1, c2, c3); | ||||
|     uint64_t r3 = c1; c1 = 0; | ||||
|     muladd_c3(a.n[3], b.n[1], c2, c3, c1); | ||||
|     muladd_c3(a.n[2], b.n[2], c2, c3, c1); | ||||
|     muladd_c3(a.n[1], b.n[3], c2, c3, c1); | ||||
|     uint64_t r4 = c2; c2 = 0; | ||||
|     muladd_c3(a.n[2], b.n[3], c3, c1, c2); | ||||
|     muladd_c3(a.n[3], b.n[2], c3, c1, c2); | ||||
|     uint64_t r5 = c3; c3 = 0; | ||||
|     muladd_c3(a.n[3], b.n[3], c1, c2, c3); | ||||
|     uint64_t r6 = c1; | ||||
|     uint64_t r7 = c2; | ||||
|     assert(c3 == 0); | ||||
|     unsigned __int128 c = (unsigned __int128)r4 * COMP_LIMB + r0; | ||||
|     r->n[0] = c; | ||||
|     c = (unsigned __int128)r5 * COMP_LIMB + r1 + (c >> 64); | ||||
|     r->n[1] = c; | ||||
|     c = (unsigned __int128)r6 * COMP_LIMB + r2 + (c >> 64); | ||||
|     r->n[2] = c; | ||||
|     c = (unsigned __int128)r7 * COMP_LIMB + r3 + (c >> 64); | ||||
|     r->n[3] = c; | ||||
|     r->n[4] = c >> 64; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef VERIFY | ||||
|     r->normalized = 0; | ||||
|     r->reduced = 0; | ||||
| #endif | ||||
|     secp256k1_fe_reduce(r); | ||||
| } | ||||
| 
 | ||||
| /*void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
 | ||||
|     secp256k1_fe_mul(r, a, a); | ||||
| }*/ | ||||
| 
 | ||||
| void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *ac) { | ||||
|     secp256k1_fe_t a = *ac; | ||||
|     secp256k1_fe_reduce(&a); | ||||
| 
 | ||||
| #ifdef USE_FIELD_5X64_ASM | ||||
|     secp256k1_fe_sqr_inner((&a)->n,r->n); | ||||
| #else | ||||
|     uint64_t c1,c2,c3; | ||||
|     c3=0; | ||||
|     mul_c2(a.n[0], a.n[0], c1, c2); | ||||
|     uint64_t r0 = c1; c1 = 0; | ||||
|     muladd2_c3(a.n[0], a.n[1], c2, c3, c1); | ||||
|     uint64_t r1 = c2; c2 = 0; | ||||
|     muladd2_c3(a.n[2], a.n[0], c3, c1, c2); | ||||
|     sqradd_c3(a.n[1], c3, c1, c2); | ||||
|     uint64_t r2 = c3; c3 = 0; | ||||
|     muladd2_c3(a.n[0], a.n[3], c1, c2, c3); | ||||
|     muladd2_c3(a.n[1], a.n[2], c1, c2, c3); | ||||
|     uint64_t r3 = c1; c1 = 0; | ||||
|     muladd2_c3(a.n[3], a.n[1], c2, c3, c1); | ||||
|     sqradd_c3(a.n[2], c2, c3, c1); | ||||
|     uint64_t r4 = c2; c2 = 0; | ||||
|     muladd2_c3(a.n[2], a.n[3], c3, c1, c2); | ||||
|     uint64_t r5 = c3; c3 = 0; | ||||
|     sqradd_c3(a.n[3], c1, c2, c3); | ||||
|     uint64_t r6 = c1; | ||||
|     uint64_t r7 = c2; | ||||
|     assert(c3 == 0); | ||||
|     unsigned __int128 c = (unsigned __int128)r4 * COMP_LIMB + r0; | ||||
|     r->n[0] = c; | ||||
|     c = (unsigned __int128)r5 * COMP_LIMB + r1 + (c >> 64); | ||||
|     r->n[1] = c; | ||||
|     c = (unsigned __int128)r6 * COMP_LIMB + r2 + (c >> 64); | ||||
|     r->n[2] = c; | ||||
|     c = (unsigned __int128)r7 * COMP_LIMB + r3 + (c >> 64); | ||||
|     r->n[3] = c; | ||||
|     r->n[4] = c >> 64; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef VERIFY | ||||
|     r->normalized = 0; | ||||
|     r->reduced = 0; | ||||
| #endif | ||||
|     secp256k1_fe_reduce(r); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										11
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x64_asm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								crypto/secp256k1/secp256k1/src/impl/field_5x64_asm.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ | ||||
| #define _SECP256K1_FIELD_INNER5X52_IMPL_H_ | ||||
| 
 | ||||
| void __attribute__ ((sysv_abi)) secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r); | ||||
| void __attribute__ ((sysv_abi)) secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										155
									
								
								crypto/secp256k1/secp256k1/src/impl/field_gmp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								crypto/secp256k1/secp256k1/src/impl/field_gmp.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,155 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_FIELD_REPR_IMPL_H_ | ||||
| #define _SECP256K1_FIELD_REPR_IMPL_H_ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #include "../num.h" | ||||
| #include "../field.h" | ||||
| 
 | ||||
| static mp_limb_t secp256k1_field_p[FIELD_LIMBS]; | ||||
| static mp_limb_t secp256k1_field_pc[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS]; | ||||
| 
 | ||||
| void static secp256k1_fe_inner_start(void) { | ||||
|     for (int i=0; i<(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; i++) | ||||
|         secp256k1_field_pc[i] = 0; | ||||
|     secp256k1_field_pc[0] += 0x3D1UL; | ||||
|     secp256k1_field_pc[32/GMP_NUMB_BITS] += (1UL << (32 % GMP_NUMB_BITS)); | ||||
|     for (int i=0; i<FIELD_LIMBS; i++) { | ||||
|         secp256k1_field_p[i] = 0; | ||||
|     } | ||||
|     mpn_sub(secp256k1_field_p, secp256k1_field_p, FIELD_LIMBS, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_inner_stop(void) { | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_normalize(secp256k1_fe_t *r) { | ||||
|     if (r->n[FIELD_LIMBS] != 0) { | ||||
| #if (GMP_NUMB_BITS >= 40) | ||||
|         mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * r->n[FIELD_LIMBS]); | ||||
|         mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * carry); | ||||
| #else | ||||
|         mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * r->n[FIELD_LIMBS]) +  | ||||
|                           mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), r->n[FIELD_LIMBS] << (32 % GMP_NUMB_BITS)); | ||||
|         mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * carry); | ||||
|         mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), carry << (32%GMP_NUMB_BITS)); | ||||
| #endif | ||||
|         r->n[FIELD_LIMBS] = 0; | ||||
|     } | ||||
|     if (mpn_cmp(r->n, secp256k1_field_p, FIELD_LIMBS) >= 0) | ||||
|         mpn_sub(r->n, r->n, FIELD_LIMBS, secp256k1_field_p, FIELD_LIMBS); | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { | ||||
|     r->n[0] = a; | ||||
|     for (int i=1; i<FIELD_LIMBS+1; i++) | ||||
|         r->n[i] = 0; | ||||
| } | ||||
| 
 | ||||
| int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) { | ||||
|     int ret = 1; | ||||
|     for (int i=0; i<FIELD_LIMBS+1; i++) | ||||
|         ret &= (a->n[i] == 0); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) { | ||||
|     return a->n[0] & 1; | ||||
| } | ||||
| 
 | ||||
| int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { | ||||
|     int ret = 1; | ||||
|     for (int i=0; i<FIELD_LIMBS+1; i++) | ||||
|         ret &= (a->n[i] == b->n[i]); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { | ||||
|     for (int i=0; i<FIELD_LIMBS+1; i++) | ||||
|         r->n[i] = 0; | ||||
|     for (int i=0; i<256; i++) { | ||||
|         int limb = i/GMP_NUMB_BITS; | ||||
|         int shift = i%GMP_NUMB_BITS; | ||||
|         r->n[limb] |= (mp_limb_t)((a[31-i/8] >> (i%8)) & 0x1) << shift; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ | ||||
| void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { | ||||
|     for (int i=0; i<32; i++) { | ||||
|         int c = 0; | ||||
|         for (int j=0; j<8; j++) { | ||||
|             int limb = (8*i+j)/GMP_NUMB_BITS; | ||||
|             int shift = (8*i+j)%GMP_NUMB_BITS; | ||||
|             c |= ((a->n[limb] >> shift) & 0x1) << j; | ||||
|         } | ||||
|         r[31-i] = c; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { | ||||
|     *r = *a; | ||||
|     secp256k1_fe_normalize(r); | ||||
|     for (int i=0; i<FIELD_LIMBS; i++) | ||||
|         r->n[i] = ~(r->n[i]); | ||||
| #if (GMP_NUMB_BITS >= 33) | ||||
|     mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x1000003D0ULL); | ||||
| #else | ||||
|     mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x3D0UL); | ||||
|     mpn_sub_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS)); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { | ||||
|     mpn_mul_1(r->n, r->n, FIELD_LIMBS+1, a); | ||||
| } | ||||
| 
 | ||||
| void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
|     mpn_add(r->n, r->n, FIELD_LIMBS+1, a->n, FIELD_LIMBS+1); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_reduce(secp256k1_fe_t *r, mp_limb_t *tmp) { | ||||
|     // <A1 A2 A3 A4> <B1 B2 B3 B4>
 | ||||
|     //       B1 B2 B3 B4
 | ||||
|     // + C * A1 A2 A3 A4
 | ||||
|     // +  A1 A2 A3 A4
 | ||||
| 
 | ||||
| #if (GMP_NUMB_BITS >= 33) | ||||
|     mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x1000003D1ULL); | ||||
| #else | ||||
|     mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x3D1UL) + | ||||
|                   mpn_addmul_1(tmp+(32/GMP_NUMB_BITS), tmp+FIELD_LIMBS, FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS)); | ||||
| #endif | ||||
|     mp_limb_t q[1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS]; | ||||
|     q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] = mpn_mul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o); | ||||
| #if (GMP_NUMB_BITS <= 32) | ||||
|     mp_limb_t o2 = tmp[2*FIELD_LIMBS-(32/GMP_NUMB_BITS)] << (32%GMP_NUMB_BITS); | ||||
|     q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] += mpn_addmul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o2); | ||||
| #endif | ||||
|     r->n[FIELD_LIMBS] = mpn_add(r->n, tmp, FIELD_LIMBS, q, 1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { | ||||
|     secp256k1_fe_t ac = *a; | ||||
|     secp256k1_fe_t bc = *b; | ||||
|     secp256k1_fe_normalize(&ac); | ||||
|     secp256k1_fe_normalize(&bc); | ||||
|     mp_limb_t tmp[2*FIELD_LIMBS]; | ||||
|     mpn_mul_n(tmp, ac.n, bc.n, FIELD_LIMBS); | ||||
|     secp256k1_fe_reduce(r, tmp); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { | ||||
|     secp256k1_fe_t ac = *a; | ||||
|     secp256k1_fe_normalize(&ac); | ||||
|     mp_limb_t tmp[2*FIELD_LIMBS]; | ||||
|     mpn_sqr(tmp, ac.n, FIELD_LIMBS); | ||||
|     secp256k1_fe_reduce(r, tmp); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										397
									
								
								crypto/secp256k1/secp256k1/src/impl/group.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										397
									
								
								crypto/secp256k1/secp256k1/src/impl/group.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,397 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_GROUP_IMPL_H_ | ||||
| #define _SECP256K1_GROUP_IMPL_H_ | ||||
| 
 | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "../num.h" | ||||
| #include "../field.h" | ||||
| #include "../group.h" | ||||
| 
 | ||||
| void static secp256k1_ge_set_infinity(secp256k1_ge_t *r) { | ||||
|     r->infinity = 1; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y) { | ||||
|     r->infinity = 0; | ||||
|     r->x = *x; | ||||
|     r->y = *y; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ge_is_infinity(const secp256k1_ge_t *a) { | ||||
|     return a->infinity; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a) { | ||||
|     r->infinity = a->infinity; | ||||
|     r->x = a->x; | ||||
|     r->y = a->y; | ||||
|     secp256k1_fe_normalize(&r->y); | ||||
|     secp256k1_fe_negate(&r->y, &r->y, 1); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a) { | ||||
|     char cx[65]; int lx=65; | ||||
|     char cy[65]; int ly=65; | ||||
|     secp256k1_fe_get_hex(cx, &lx, &a->x); | ||||
|     secp256k1_fe_get_hex(cy, &ly, &a->y); | ||||
|     lx = strlen(cx); | ||||
|     ly = strlen(cy); | ||||
|     int len = lx + ly + 3 + 1; | ||||
|     if (*rlen < len) { | ||||
|         *rlen = len; | ||||
|         return; | ||||
|     } | ||||
|     *rlen = len; | ||||
|     r[0] = '('; | ||||
|     memcpy(r+1, cx, lx); | ||||
|     r[1+lx] = ','; | ||||
|     memcpy(r+2+lx, cy, ly); | ||||
|     r[2+lx+ly] = ')'; | ||||
|     r[3+lx+ly] = 0; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) { | ||||
|     secp256k1_fe_inv_var(&a->z, &a->z); | ||||
|     secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z); | ||||
|     secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &a->z, &z2); | ||||
|     secp256k1_fe_mul(&a->x, &a->x, &z2); | ||||
|     secp256k1_fe_mul(&a->y, &a->y, &z3); | ||||
|     secp256k1_fe_set_int(&a->z, 1); | ||||
|     r->infinity = a->infinity; | ||||
|     r->x = a->x; | ||||
|     r->y = a->y; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_set_infinity(secp256k1_gej_t *r) { | ||||
|     r->infinity = 1; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y) { | ||||
|     r->infinity = 0; | ||||
|     r->x = *x; | ||||
|     r->y = *y; | ||||
|     secp256k1_fe_set_int(&r->z, 1); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd) { | ||||
|     r->x = *x; | ||||
|     secp256k1_fe_t x2; secp256k1_fe_sqr(&x2, x); | ||||
|     secp256k1_fe_t x3; secp256k1_fe_mul(&x3, x, &x2); | ||||
|     r->infinity = 0; | ||||
|     secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7); | ||||
|     secp256k1_fe_add(&c, &x3); | ||||
|     secp256k1_fe_sqrt(&r->y, &c); | ||||
|     secp256k1_fe_normalize(&r->y); | ||||
|     if (secp256k1_fe_is_odd(&r->y) != odd) | ||||
|         secp256k1_fe_negate(&r->y, &r->y, 1); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) { | ||||
|    r->infinity = a->infinity; | ||||
|    r->x = a->x; | ||||
|    r->y = a->y; | ||||
|    secp256k1_fe_set_int(&r->z, 1); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_get_x(secp256k1_fe_t *r, const secp256k1_gej_t *a) { | ||||
|     secp256k1_fe_t zi2; secp256k1_fe_inv_var(&zi2, &a->z); secp256k1_fe_sqr(&zi2, &zi2); | ||||
|     secp256k1_fe_mul(r, &a->x, &zi2); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a) { | ||||
|     r->infinity = a->infinity; | ||||
|     r->x = a->x; | ||||
|     r->y = a->y; | ||||
|     r->z = a->z; | ||||
|     secp256k1_fe_normalize(&r->y); | ||||
|     secp256k1_fe_negate(&r->y, &r->y, 1); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_gej_is_infinity(const secp256k1_gej_t *a) { | ||||
|     return a->infinity; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_gej_is_valid(const secp256k1_gej_t *a) { | ||||
|     if (a->infinity) | ||||
|         return 0; | ||||
|     // y^2 = x^3 + 7
 | ||||
|     // (Y/Z^3)^2 = (X/Z^2)^3 + 7
 | ||||
|     // Y^2 / Z^6 = X^3 / Z^6 + 7
 | ||||
|     // Y^2 = X^3 + 7*Z^6
 | ||||
|     secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y); | ||||
|     secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); | ||||
|     secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z); | ||||
|     secp256k1_fe_t z6; secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); | ||||
|     secp256k1_fe_mul_int(&z6, 7); | ||||
|     secp256k1_fe_add(&x3, &z6); | ||||
|     secp256k1_fe_normalize(&y2); | ||||
|     secp256k1_fe_normalize(&x3); | ||||
|     return secp256k1_fe_equal(&y2, &x3); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_ge_is_valid(const secp256k1_ge_t *a) { | ||||
|     if (a->infinity) | ||||
|         return 0; | ||||
|     // y^2 = x^3 + 7
 | ||||
|     secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y); | ||||
|     secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); | ||||
|     secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7); | ||||
|     secp256k1_fe_add(&x3, &c); | ||||
|     secp256k1_fe_normalize(&y2); | ||||
|     secp256k1_fe_normalize(&x3); | ||||
|     return secp256k1_fe_equal(&y2, &x3); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a) { | ||||
|     secp256k1_fe_t t5 = a->y; | ||||
|     secp256k1_fe_normalize(&t5); | ||||
|     if (a->infinity || secp256k1_fe_is_zero(&t5)) { | ||||
|         r->infinity = 1; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     secp256k1_fe_t t1,t2,t3,t4; | ||||
|     secp256k1_fe_mul(&r->z, &t5, &a->z); | ||||
|     secp256k1_fe_mul_int(&r->z, 2);       // Z' = 2*Y*Z (2)
 | ||||
|     secp256k1_fe_sqr(&t1, &a->x); | ||||
|     secp256k1_fe_mul_int(&t1, 3);         // T1 = 3*X^2 (3)
 | ||||
|     secp256k1_fe_sqr(&t2, &t1);           // T2 = 9*X^4 (1)
 | ||||
|     secp256k1_fe_sqr(&t3, &t5); | ||||
|     secp256k1_fe_mul_int(&t3, 2);         // T3 = 2*Y^2 (2)
 | ||||
|     secp256k1_fe_sqr(&t4, &t3); | ||||
|     secp256k1_fe_mul_int(&t4, 2);         // T4 = 8*Y^4 (2)
 | ||||
|     secp256k1_fe_mul(&t3, &a->x, &t3);    // T3 = 2*X*Y^2 (1)
 | ||||
|     r->x = t3; | ||||
|     secp256k1_fe_mul_int(&r->x, 4);       // X' = 8*X*Y^2 (4)
 | ||||
|     secp256k1_fe_negate(&r->x, &r->x, 4); // X' = -8*X*Y^2 (5)
 | ||||
|     secp256k1_fe_add(&r->x, &t2);         // X' = 9*X^4 - 8*X*Y^2 (6)
 | ||||
|     secp256k1_fe_negate(&t2, &t2, 1);     // T2 = -9*X^4 (2)
 | ||||
|     secp256k1_fe_mul_int(&t3, 6);         // T3 = 12*X*Y^2 (6)
 | ||||
|     secp256k1_fe_add(&t3, &t2);           // T3 = 12*X*Y^2 - 9*X^4 (8)
 | ||||
|     secp256k1_fe_mul(&r->y, &t1, &t3);    // Y' = 36*X^3*Y^2 - 27*X^6 (1)
 | ||||
|     secp256k1_fe_negate(&t2, &t4, 2);     // T2 = -8*Y^4 (3)
 | ||||
|     secp256k1_fe_add(&r->y, &t2);         // Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4)
 | ||||
|     r->infinity = 0; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) { | ||||
|     if (a->infinity) { | ||||
|         *r = *b; | ||||
|         return; | ||||
|     } | ||||
|     if (b->infinity) { | ||||
|         *r = *a; | ||||
|         return; | ||||
|     } | ||||
|     r->infinity = 0; | ||||
|     secp256k1_fe_t z22; secp256k1_fe_sqr(&z22, &b->z); | ||||
|     secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z); | ||||
|     secp256k1_fe_t u1; secp256k1_fe_mul(&u1, &a->x, &z22); | ||||
|     secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12); | ||||
|     secp256k1_fe_t s1; secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); | ||||
|     secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); | ||||
|     secp256k1_fe_normalize(&u1); | ||||
|     secp256k1_fe_normalize(&u2); | ||||
|     if (secp256k1_fe_equal(&u1, &u2)) { | ||||
|         secp256k1_fe_normalize(&s1); | ||||
|         secp256k1_fe_normalize(&s2); | ||||
|         if (secp256k1_fe_equal(&s1, &s2)) { | ||||
|             secp256k1_gej_double(r, a); | ||||
|         } else { | ||||
|             r->infinity = 1; | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|     secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); | ||||
|     secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); | ||||
|     secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i); | ||||
|     secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h); | ||||
|     secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2); | ||||
|     secp256k1_fe_mul(&r->z, &a->z, &b->z); secp256k1_fe_mul(&r->z, &r->z, &h); | ||||
|     secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2); | ||||
|     r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); | ||||
|     secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); | ||||
|     secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); | ||||
|     secp256k1_fe_add(&r->y, &h3); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) { | ||||
|     if (a->infinity) { | ||||
|         r->infinity = b->infinity; | ||||
|         r->x = b->x; | ||||
|         r->y = b->y; | ||||
|         secp256k1_fe_set_int(&r->z, 1); | ||||
|         return; | ||||
|     } | ||||
|     if (b->infinity) { | ||||
|         *r = *a; | ||||
|         return; | ||||
|     } | ||||
|     r->infinity = 0; | ||||
|     secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z); | ||||
|     secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize(&u1); | ||||
|     secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12); | ||||
|     secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize(&s1); | ||||
|     secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); | ||||
|     secp256k1_fe_normalize(&u1); | ||||
|     secp256k1_fe_normalize(&u2); | ||||
|     if (secp256k1_fe_equal(&u1, &u2)) { | ||||
|         secp256k1_fe_normalize(&s1); | ||||
|         secp256k1_fe_normalize(&s2); | ||||
|         if (secp256k1_fe_equal(&s1, &s2)) { | ||||
|             secp256k1_gej_double(r, a); | ||||
|         } else { | ||||
|             r->infinity = 1; | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|     secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); | ||||
|     secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); | ||||
|     secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i); | ||||
|     secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h); | ||||
|     secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2); | ||||
|     r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); | ||||
|     secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2); | ||||
|     r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); | ||||
|     secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); | ||||
|     secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); | ||||
|     secp256k1_fe_add(&r->y, &h3); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a) { | ||||
|     secp256k1_gej_t c = *a; | ||||
|     secp256k1_ge_t t; secp256k1_ge_set_gej(&t, &c); | ||||
|     secp256k1_ge_get_hex(r, rlen, &t); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a) { | ||||
|     const secp256k1_fe_t *beta = &secp256k1_ge_consts->beta; | ||||
|     *r = *a; | ||||
|     secp256k1_fe_mul(&r->x, &r->x, beta); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) { | ||||
|     const secp256k1_ge_consts_t *c = secp256k1_ge_consts; | ||||
|     secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2; | ||||
| 
 | ||||
|     secp256k1_num_init(&bnc1); | ||||
|     secp256k1_num_init(&bnc2); | ||||
|     secp256k1_num_init(&bnt1); | ||||
|     secp256k1_num_init(&bnt2); | ||||
|     secp256k1_num_init(&bnn2); | ||||
| 
 | ||||
|     secp256k1_num_copy(&bnn2, &c->order); | ||||
|     secp256k1_num_shift(&bnn2, 1); | ||||
| 
 | ||||
|     secp256k1_num_mul(&bnc1, a, &c->a1b2); | ||||
|     secp256k1_num_add(&bnc1, &bnc1, &bnn2); | ||||
|     secp256k1_num_div(&bnc1, &bnc1, &c->order); | ||||
| 
 | ||||
|     secp256k1_num_mul(&bnc2, a, &c->b1); | ||||
|     secp256k1_num_add(&bnc2, &bnc2, &bnn2); | ||||
|     secp256k1_num_div(&bnc2, &bnc2, &c->order); | ||||
| 
 | ||||
|     secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2); | ||||
|     secp256k1_num_mul(&bnt2, &bnc2, &c->a2); | ||||
|     secp256k1_num_add(&bnt1, &bnt1, &bnt2); | ||||
|     secp256k1_num_sub(r1, a, &bnt1); | ||||
|     secp256k1_num_mul(&bnt1, &bnc1, &c->b1); | ||||
|     secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2); | ||||
|     secp256k1_num_sub(r2, &bnt1, &bnt2); | ||||
| 
 | ||||
|     secp256k1_num_free(&bnc1); | ||||
|     secp256k1_num_free(&bnc2); | ||||
|     secp256k1_num_free(&bnt1); | ||||
|     secp256k1_num_free(&bnt2); | ||||
|     secp256k1_num_free(&bnn2); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void static secp256k1_ge_start(void) { | ||||
|     static const unsigned char secp256k1_ge_consts_order[] = { | ||||
|         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | ||||
|         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, | ||||
|         0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, | ||||
|         0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 | ||||
|     }; | ||||
|     static const unsigned char secp256k1_ge_consts_g_x[] = { | ||||
|         0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC, | ||||
|         0x55,0xA0,0x62,0x95,0xCE,0x87,0x0B,0x07, | ||||
|         0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9, | ||||
|         0x59,0xF2,0x81,0x5B,0x16,0xF8,0x17,0x98 | ||||
|     }; | ||||
|     static const unsigned char secp256k1_ge_consts_g_y[] = { | ||||
|         0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65, | ||||
|         0x5D,0xA4,0xFB,0xFC,0x0E,0x11,0x08,0xA8, | ||||
|         0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19, | ||||
|         0x9C,0x47,0xD0,0x8F,0xFB,0x10,0xD4,0xB8 | ||||
|     }; | ||||
|     // properties of secp256k1's efficiently computable endomorphism
 | ||||
|     static const unsigned char secp256k1_ge_consts_lambda[] = { | ||||
|         0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0, | ||||
|         0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, | ||||
|         0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78, | ||||
|         0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72 | ||||
|     }; | ||||
|     static const unsigned char secp256k1_ge_consts_beta[] = { | ||||
|         0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10, | ||||
|         0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9, | ||||
|         0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95, | ||||
|         0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee | ||||
|     }; | ||||
|     static const unsigned char secp256k1_ge_consts_a1b2[] = { | ||||
|         0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd, | ||||
|         0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15 | ||||
|     }; | ||||
|     static const unsigned char secp256k1_ge_consts_b1[] = { | ||||
|         0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28, | ||||
|         0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3 | ||||
|     }; | ||||
|     static const unsigned char secp256k1_ge_consts_a2[] = { | ||||
|         0x01, | ||||
|         0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6, | ||||
|         0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8 | ||||
|     }; | ||||
|     if (secp256k1_ge_consts == NULL) { | ||||
|         secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)malloc(sizeof(secp256k1_ge_consts_t)); | ||||
|         secp256k1_num_init(&ret->order); | ||||
|         secp256k1_num_init(&ret->half_order); | ||||
|         secp256k1_num_init(&ret->lambda); | ||||
|         secp256k1_num_init(&ret->a1b2); | ||||
|         secp256k1_num_init(&ret->a2); | ||||
|         secp256k1_num_init(&ret->b1); | ||||
|         secp256k1_num_set_bin(&ret->order,  secp256k1_ge_consts_order,  sizeof(secp256k1_ge_consts_order)); | ||||
|         secp256k1_num_set_bin(&ret->lambda, secp256k1_ge_consts_lambda, sizeof(secp256k1_ge_consts_lambda)); | ||||
|         secp256k1_num_set_bin(&ret->a1b2,   secp256k1_ge_consts_a1b2,   sizeof(secp256k1_ge_consts_a1b2)); | ||||
|         secp256k1_num_set_bin(&ret->a2,     secp256k1_ge_consts_a2,     sizeof(secp256k1_ge_consts_a2)); | ||||
|         secp256k1_num_set_bin(&ret->b1,     secp256k1_ge_consts_b1,     sizeof(secp256k1_ge_consts_b1)); | ||||
|         secp256k1_num_copy(&ret->half_order, &ret->order); | ||||
|         secp256k1_num_shift(&ret->half_order, 1); | ||||
|         secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta); | ||||
|         secp256k1_fe_t g_x, g_y; | ||||
|         secp256k1_fe_set_b32(&g_x, secp256k1_ge_consts_g_x); | ||||
|         secp256k1_fe_set_b32(&g_y, secp256k1_ge_consts_g_y); | ||||
|         secp256k1_ge_set_xy(&ret->g, &g_x, &g_y); | ||||
|         secp256k1_ge_consts = ret; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_ge_stop(void) { | ||||
|     if (secp256k1_ge_consts != NULL) { | ||||
|         secp256k1_ge_consts_t *c = (secp256k1_ge_consts_t*)secp256k1_ge_consts; | ||||
|         secp256k1_num_free(&c->order); | ||||
|         secp256k1_num_free(&c->half_order); | ||||
|         secp256k1_num_free(&c->lambda); | ||||
|         secp256k1_num_free(&c->a1b2); | ||||
|         secp256k1_num_free(&c->a2); | ||||
|         secp256k1_num_free(&c->b1); | ||||
|         free((void*)c); | ||||
|         secp256k1_ge_consts = NULL; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										18
									
								
								crypto/secp256k1/secp256k1/src/impl/num.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								crypto/secp256k1/secp256k1/src/impl/num.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_NUM_IMPL_H_ | ||||
| #define _SECP256K1_NUM_IMPL_H_ | ||||
| 
 | ||||
| #include "../num.h" | ||||
| 
 | ||||
| #if defined(USE_NUM_GMP) | ||||
| #include "num_gmp.h" | ||||
| #elif defined(USE_NUM_OPENSSL) | ||||
| #include "num_openssl.h" | ||||
| #else | ||||
| #error "Please select num implementation" | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										346
									
								
								crypto/secp256k1/secp256k1/src/impl/num_gmp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										346
									
								
								crypto/secp256k1/secp256k1/src/impl/num_gmp.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,346 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_NUM_REPR_IMPL_H_ | ||||
| #define _SECP256K1_NUM_REPR_IMPL_H_ | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <gmp.h> | ||||
| 
 | ||||
| #include "num.h" | ||||
| 
 | ||||
| #ifdef VERIFY | ||||
| void static secp256k1_num_sanity(const secp256k1_num_t *a) { | ||||
|     assert(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0)); | ||||
| } | ||||
| #else | ||||
| #define secp256k1_num_sanity(a) do { } while(0) | ||||
| #endif | ||||
| 
 | ||||
| void static secp256k1_num_init(secp256k1_num_t *r) { | ||||
|     r->neg = 0; | ||||
|     r->limbs = 1; | ||||
|     r->data[0] = 0; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_free(secp256k1_num_t *r) { | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) { | ||||
|     *r = *a; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_bits(const secp256k1_num_t *a) { | ||||
|     int ret=(a->limbs-1)*GMP_NUMB_BITS; | ||||
|     mp_limb_t x=a->data[a->limbs-1]; | ||||
|     while (x) { | ||||
|         x >>= 1; | ||||
|         ret++; | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) { | ||||
|     unsigned char tmp[65]; | ||||
|     int len = 0; | ||||
|     if (a->limbs>1 || a->data[0] != 0) { | ||||
|         len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs); | ||||
|     } | ||||
|     int shift = 0; | ||||
|     while (shift < len && tmp[shift] == 0) shift++; | ||||
|     assert(len-shift <= rlen); | ||||
|     memset(r, 0, rlen - len + shift); | ||||
|     if (len > shift) | ||||
|         memcpy(r + rlen - len + shift, tmp + shift, len - shift); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) { | ||||
|     assert(alen > 0); | ||||
|     assert(alen <= 64); | ||||
|     int len = mpn_set_str(r->data, a, alen, 256); | ||||
|     assert(len <= NUM_LIMBS*2); | ||||
|     r->limbs = len; | ||||
|     r->neg = 0; | ||||
|     while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_set_int(secp256k1_num_t *r, int a) { | ||||
|     r->limbs = 1; | ||||
|     r->neg = (a < 0); | ||||
|     r->data[0] = (a < 0) ? -a : a; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); | ||||
|     r->limbs = a->limbs; | ||||
|     if (c != 0) { | ||||
|         assert(r->limbs < 2*NUM_LIMBS); | ||||
|         r->data[r->limbs++] = c; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_sub_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); | ||||
|     assert(c == 0); | ||||
|     r->limbs = a->limbs; | ||||
|     while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) { | ||||
|     secp256k1_num_sanity(r); | ||||
|     secp256k1_num_sanity(m); | ||||
| 
 | ||||
|     if (r->limbs >= m->limbs) { | ||||
|         mp_limb_t t[2*NUM_LIMBS]; | ||||
|         mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs); | ||||
|         r->limbs = m->limbs; | ||||
|         while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; | ||||
|     } | ||||
| 
 | ||||
|     if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { | ||||
|         secp256k1_num_sub_abs(r, m, r); | ||||
|         r->neg = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) { | ||||
|     secp256k1_num_sanity(a); | ||||
|     secp256k1_num_sanity(m); | ||||
| 
 | ||||
|     // mpn_gcdext computes: (G,S) = gcdext(U,V), where
 | ||||
|     // * G = gcd(U,V)
 | ||||
|     // * G = U*S + V*T
 | ||||
|     // * U has equal or more limbs than V, and V has no padding
 | ||||
|     // If we set U to be (a padded version of) a, and V = m:
 | ||||
|     //   G = a*S + m*T
 | ||||
|     //   G = a*S mod m
 | ||||
|     // Assuming G=1:
 | ||||
|     //   S = 1/a mod m
 | ||||
|     assert(m->limbs <= NUM_LIMBS); | ||||
|     assert(m->data[m->limbs-1] != 0); | ||||
|     mp_limb_t g[NUM_LIMBS+1]; | ||||
|     mp_limb_t u[NUM_LIMBS+1]; | ||||
|     mp_limb_t v[NUM_LIMBS+1]; | ||||
|     for (int i=0; i < m->limbs; i++) { | ||||
|         u[i] = (i < a->limbs) ? a->data[i] : 0; | ||||
|         v[i] = m->data[i]; | ||||
|     } | ||||
|     mp_size_t sn = NUM_LIMBS+1; | ||||
|     mp_size_t gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs); | ||||
|     assert(gn == 1); | ||||
|     assert(g[0] == 1); | ||||
|     r->neg = a->neg ^ m->neg; | ||||
|     if (sn < 0) { | ||||
|         mpn_sub(r->data, m->data, m->limbs, r->data, -sn); | ||||
|         r->limbs = m->limbs; | ||||
|         while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; | ||||
|     } else { | ||||
|         r->limbs = sn; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_is_zero(const secp256k1_num_t *a) { | ||||
|     return (a->limbs == 1 && a->data[0] == 0); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_is_odd(const secp256k1_num_t *a) { | ||||
|     return a->data[0] & 1; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_is_neg(const secp256k1_num_t *a) { | ||||
|     return (a->limbs > 1 || a->data[0] != 0) && a->neg; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     if (a->limbs > b->limbs) return 1; | ||||
|     if (a->limbs < b->limbs) return -1; | ||||
|     return mpn_cmp(a->data, b->data, a->limbs); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_subadd(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, int bneg) { | ||||
|     if (!(b->neg ^ bneg ^ a->neg)) { // a and b have the same sign
 | ||||
|         r->neg = a->neg; | ||||
|         if (a->limbs >= b->limbs) { | ||||
|             secp256k1_num_add_abs(r, a, b); | ||||
|         } else { | ||||
|             secp256k1_num_add_abs(r, b, a); | ||||
|         } | ||||
|     } else { | ||||
|         if (secp256k1_num_cmp(a, b) > 0) { | ||||
|             r->neg = a->neg; | ||||
|             secp256k1_num_sub_abs(r, a, b); | ||||
|         } else { | ||||
|             r->neg = b->neg ^ bneg; | ||||
|             secp256k1_num_sub_abs(r, b, a); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     secp256k1_num_sanity(a); | ||||
|     secp256k1_num_sanity(b); | ||||
|     secp256k1_num_subadd(r, a, b, 0); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     secp256k1_num_sanity(a); | ||||
|     secp256k1_num_sanity(b); | ||||
|     secp256k1_num_subadd(r, a, b, 1); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     secp256k1_num_sanity(a); | ||||
|     secp256k1_num_sanity(b); | ||||
| 
 | ||||
|     mp_limb_t tmp[2*NUM_LIMBS+1]; | ||||
|     assert(a->limbs + b->limbs <= 2*NUM_LIMBS+1); | ||||
|     if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) { | ||||
|         r->limbs = 1; | ||||
|         r->neg = 0; | ||||
|         r->data[0] = 0; | ||||
|         return; | ||||
|     } | ||||
|     if (a->limbs >= b->limbs) | ||||
|         mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs); | ||||
|     else | ||||
|         mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs); | ||||
|     r->limbs = a->limbs + b->limbs; | ||||
|     if (r->limbs > 1 && tmp[r->limbs - 1]==0) r->limbs--; | ||||
|     assert(r->limbs <= 2*NUM_LIMBS); | ||||
|     mpn_copyi(r->data, tmp, r->limbs); | ||||
|     r->neg = a->neg ^ b->neg; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     secp256k1_num_sanity(a); | ||||
|     secp256k1_num_sanity(b); | ||||
|     if (b->limbs > a->limbs) { | ||||
|         r->limbs = 1; | ||||
|         r->data[0] = 0; | ||||
|         r->neg = 0; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     mp_limb_t quo[2*NUM_LIMBS+1]; | ||||
|     mp_limb_t rem[2*NUM_LIMBS+1]; | ||||
|     mpn_tdiv_qr(quo, rem, 0, a->data, a->limbs, b->data, b->limbs); | ||||
|     mpn_copyi(r->data, quo, a->limbs - b->limbs + 1); | ||||
|     r->limbs = a->limbs - b->limbs + 1; | ||||
|     while (r->limbs > 1 && r->data[r->limbs - 1]==0) r->limbs--; | ||||
|     r->neg = a->neg ^ b->neg; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) { | ||||
|     secp256k1_num_mul(r, a, b); | ||||
|     secp256k1_num_mod(r, m); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int static secp256k1_num_shift(secp256k1_num_t *r, int bits) { | ||||
|     assert(bits <= GMP_NUMB_BITS); | ||||
|     mp_limb_t ret = mpn_rshift(r->data, r->data, r->limbs, bits); | ||||
|     if (r->limbs>1 && r->data[r->limbs-1]==0) r->limbs--; | ||||
|     ret >>= (GMP_NUMB_BITS - bits); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) { | ||||
|     return (a->limbs*GMP_NUMB_BITS > pos) && ((a->data[pos/GMP_NUMB_BITS] >> (pos % GMP_NUMB_BITS)) & 1); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_inc(secp256k1_num_t *r) { | ||||
|     mp_limb_t ret = mpn_add_1(r->data, r->data, r->limbs, (mp_limb_t)1); | ||||
|     if (ret) { | ||||
|         assert(r->limbs < 2*NUM_LIMBS); | ||||
|         r->data[r->limbs++] = ret; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) { | ||||
|     static const unsigned char cvt[256] = { | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0, | ||||
|         0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, | ||||
|         0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0 | ||||
|     }; | ||||
|     unsigned char num[257] = {}; | ||||
|     for (int i=0; i<alen; i++) { | ||||
|         num[i] = cvt[a[i]]; | ||||
|     } | ||||
|     r->limbs = mpn_set_str(r->data, num, alen, 16); | ||||
|     while (r->limbs > 1 && r->data[r->limbs-1] == 0) r->limbs--; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) { | ||||
|     static const unsigned char cvt[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | ||||
|     unsigned char *tmp = malloc(257); | ||||
|     mp_size_t len = mpn_get_str(tmp, 16, (mp_limb_t*)a->data, a->limbs); | ||||
|     assert(len <= rlen); | ||||
|     for (int i=0; i<len; i++) { | ||||
|         assert(rlen-len+i >= 0); | ||||
|         assert(rlen-len+i < rlen); | ||||
|         assert(tmp[i] >= 0); | ||||
|         assert(tmp[i] < 16); | ||||
|         r[rlen-len+i] = cvt[tmp[i]]; | ||||
|     } | ||||
|     for (int i=0; i<rlen-len; i++) { | ||||
|         assert(i >= 0); | ||||
|         assert(i < rlen); | ||||
|         r[i] = cvt[0]; | ||||
|     } | ||||
|     free(tmp); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) { | ||||
|     assert(bits > 0); | ||||
|     rh->neg = a->neg; | ||||
|     if (bits >= a->limbs * GMP_NUMB_BITS) { | ||||
|         *rl = *a; | ||||
|         rh->limbs = 1; | ||||
|         rh->data[0] = 0; | ||||
|         return; | ||||
|     } | ||||
|     rl->limbs = 0; | ||||
|     rl->neg = a->neg; | ||||
|     int left = bits; | ||||
|     while (left >= GMP_NUMB_BITS) { | ||||
|         rl->data[rl->limbs] = a->data[rl->limbs]; | ||||
|         rl->limbs++; | ||||
|         left -= GMP_NUMB_BITS; | ||||
|     } | ||||
|     if (left == 0) { | ||||
|         mpn_copyi(rh->data, a->data + rl->limbs, a->limbs - rl->limbs); | ||||
|         rh->limbs = a->limbs - rl->limbs; | ||||
|     } else { | ||||
|         mpn_rshift(rh->data, a->data + rl->limbs, a->limbs - rl->limbs, left); | ||||
|         rh->limbs = a->limbs - rl->limbs; | ||||
|         while (rh->limbs>1 && rh->data[rh->limbs-1]==0) rh->limbs--; | ||||
|     } | ||||
|     if (left > 0) { | ||||
|         rl->data[rl->limbs] = a->data[rl->limbs] & ((((mp_limb_t)1) << left) - 1); | ||||
|         rl->limbs++; | ||||
|     } | ||||
|     while (rl->limbs>1 && rl->data[rl->limbs-1]==0) rl->limbs--; | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_negate(secp256k1_num_t *r) { | ||||
|     r->neg ^= 1; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										145
									
								
								crypto/secp256k1/secp256k1/src/impl/num_openssl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								crypto/secp256k1/secp256k1/src/impl/num_openssl.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,145 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_NUM_REPR_IMPL_H_ | ||||
| #define _SECP256K1_NUM_REPR_IMPL_H_ | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <openssl/bn.h> | ||||
| #include <openssl/crypto.h> | ||||
| 
 | ||||
| #include "../num.h" | ||||
| 
 | ||||
| void static secp256k1_num_init(secp256k1_num_t *r) { | ||||
|     BN_init(&r->bn); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_free(secp256k1_num_t *r) { | ||||
|     BN_free(&r->bn); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) { | ||||
|     BN_copy(&r->bn, &a->bn); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) { | ||||
|     unsigned int size = BN_num_bytes(&a->bn); | ||||
|     assert(size <= rlen); | ||||
|     memset(r,0,rlen); | ||||
|     BN_bn2bin(&a->bn, r + rlen - size); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) { | ||||
|     BN_bin2bn(a, alen, &r->bn); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_set_int(secp256k1_num_t *r, int a) { | ||||
|     BN_set_word(&r->bn, a < 0 ? -a : a); | ||||
|     BN_set_negative(&r->bn, a < 0); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) { | ||||
|     BN_CTX *ctx = BN_CTX_new(); | ||||
|     BN_mod_inverse(&r->bn, &a->bn, &m->bn, ctx); | ||||
|     BN_CTX_free(ctx); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) { | ||||
|     BN_CTX *ctx = BN_CTX_new(); | ||||
|     BN_mod_mul(&r->bn, &a->bn, &b->bn, &m->bn, ctx); | ||||
|     BN_CTX_free(ctx); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     return BN_cmp(&a->bn, &b->bn); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     BN_add(&r->bn, &a->bn, &b->bn); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     BN_sub(&r->bn, &a->bn, &b->bn); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     BN_CTX *ctx = BN_CTX_new(); | ||||
|     BN_mul(&r->bn, &a->bn, &b->bn, ctx); | ||||
|     BN_CTX_free(ctx); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { | ||||
|     BN_CTX *ctx = BN_CTX_new(); | ||||
|     BN_div(&r->bn, NULL, &a->bn, &b->bn, ctx); | ||||
|     BN_CTX_free(ctx); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) { | ||||
|     BN_CTX *ctx = BN_CTX_new(); | ||||
|     BN_nnmod(&r->bn, &r->bn, &m->bn, ctx); | ||||
|     BN_CTX_free(ctx); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_bits(const secp256k1_num_t *a) { | ||||
|     return BN_num_bits(&a->bn); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_shift(secp256k1_num_t *r, int bits) { | ||||
|     int ret = BN_is_zero(&r->bn) ? 0 : r->bn.d[0] & ((1 << bits) - 1); | ||||
|     BN_rshift(&r->bn, &r->bn, bits); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_is_zero(const secp256k1_num_t *a) { | ||||
|     return BN_is_zero(&a->bn); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_is_odd(const secp256k1_num_t *a) { | ||||
|     return BN_is_odd(&a->bn); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_is_neg(const secp256k1_num_t *a) { | ||||
|     return BN_is_negative(&a->bn); | ||||
| } | ||||
| 
 | ||||
| int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) { | ||||
|     return BN_is_bit_set(&a->bn, pos); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_inc(secp256k1_num_t *r) { | ||||
|     BN_add_word(&r->bn, 1); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) { | ||||
|     char *str = (char*)malloc(alen+1); | ||||
|     memcpy(str, a, alen); | ||||
|     str[alen] = 0; | ||||
|     BIGNUM *pbn = &r->bn; | ||||
|     BN_hex2bn(&pbn, str); | ||||
|     free(str); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) { | ||||
|     char *str = BN_bn2hex(&a->bn); | ||||
|     int len = strlen(str); | ||||
|     assert(rlen >= len); | ||||
|     for (int i=0; i<rlen-len; i++) | ||||
|         r[i] = '0'; | ||||
|     memcpy(r+rlen-len, str, len); | ||||
|     OPENSSL_free(str); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) { | ||||
|     BN_copy(&rl->bn, &a->bn); | ||||
|     BN_rshift(&rh->bn, &a->bn, bits); | ||||
|     BN_mask_bits(&rl->bn, bits); | ||||
| } | ||||
| 
 | ||||
| void static secp256k1_num_negate(secp256k1_num_t *r) { | ||||
|     BN_set_negative(&r->bn, !BN_is_negative(&r->bn)); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										45
									
								
								crypto/secp256k1/secp256k1/src/impl/util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								crypto/secp256k1/secp256k1/src/impl/util.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_UTIL_IMPL_H_ | ||||
| #define _SECP256K1_UTIL_IMPL_H_ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "../util.h" | ||||
| 
 | ||||
| static inline uint32_t secp256k1_rand32(void) { | ||||
|     static uint32_t Rz = 11, Rw = 11; | ||||
|     Rz = 36969 * (Rz & 0xFFFF) + (Rz >> 16); | ||||
|     Rw = 18000 * (Rw & 0xFFFF) + (Rw >> 16); | ||||
|     return (Rw << 16) + (Rw >> 16) + Rz; | ||||
| } | ||||
| 
 | ||||
| static void secp256k1_rand256(unsigned char *b32) { | ||||
|     for (int i=0; i<8; i++) { | ||||
|         uint32_t r = secp256k1_rand32(); | ||||
|         b32[i*4 + 0] = (r >>  0) & 0xFF; | ||||
|         b32[i*4 + 1] = (r >>  8) & 0xFF; | ||||
|         b32[i*4 + 2] = (r >> 16) & 0xFF; | ||||
|         b32[i*4 + 3] = (r >> 24) & 0xFF; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void secp256k1_rand256_test(unsigned char *b32) { | ||||
|     int bits=0; | ||||
|     memset(b32, 0, 32); | ||||
|     while (bits < 256) { | ||||
|         uint32_t ent = secp256k1_rand32(); | ||||
|         int now = 1 + ((ent % 64)*((ent >> 6) % 32)+16)/31; | ||||
|         uint32_t val = 1 & (ent >> 11); | ||||
|         while (now > 0 && bits < 256) { | ||||
|             b32[bits / 8] |= val << (bits % 8); | ||||
|             now--; | ||||
|             bits++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| @ -0,0 +1,60 @@ | ||||
| package org.bitcoin; | ||||
| 
 | ||||
| import java.nio.ByteBuffer; | ||||
| import java.nio.ByteOrder; | ||||
| 
 | ||||
| import com.google.common.base.Preconditions; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * This class holds native methods to handle ECDSA verification. | ||||
|  * You can find an example library that can be used for this at | ||||
|  * https://github.com/sipa/secp256k1 | ||||
|  */ | ||||
| public class NativeSecp256k1 { | ||||
|     public static final boolean enabled; | ||||
|     static { | ||||
|         boolean isEnabled = true; | ||||
|         try { | ||||
|             System.loadLibrary("javasecp256k1"); | ||||
|         } catch (UnsatisfiedLinkError e) { | ||||
|             isEnabled = false; | ||||
|         } | ||||
|         enabled = isEnabled; | ||||
|     } | ||||
|      | ||||
|     private static ThreadLocal<ByteBuffer> nativeECDSABuffer = new ThreadLocal<ByteBuffer>(); | ||||
|     /** | ||||
|      * Verifies the given secp256k1 signature in native code. | ||||
|      * Calling when enabled == false is undefined (probably library not loaded) | ||||
|      *  | ||||
|      * @param data The data which was signed, must be exactly 32 bytes | ||||
|      * @param signature The signature | ||||
|      * @param pub The public key which did the signing | ||||
|      */ | ||||
|     public static boolean verify(byte[] data, byte[] signature, byte[] pub) { | ||||
|         Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); | ||||
| 
 | ||||
|         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||
|         if (byteBuff == null) { | ||||
|             byteBuff = ByteBuffer.allocateDirect(32 + 8 + 520 + 520); | ||||
|             byteBuff.order(ByteOrder.nativeOrder()); | ||||
|             nativeECDSABuffer.set(byteBuff); | ||||
|         } | ||||
|         byteBuff.rewind(); | ||||
|         byteBuff.put(data); | ||||
|         byteBuff.putInt(signature.length); | ||||
|         byteBuff.putInt(pub.length); | ||||
|         byteBuff.put(signature); | ||||
|         byteBuff.put(pub); | ||||
|         return secp256k1_ecdsa_verify(byteBuff) == 1; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param byteBuff signature format is byte[32] data, | ||||
|      *        native-endian int signatureLength, native-endian int pubkeyLength, | ||||
|      *        byte[signatureLength] signature, byte[pubkeyLength] pub | ||||
|      * @returns 1 for valid signature, anything else for invalid | ||||
|      */ | ||||
|     private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff); | ||||
| } | ||||
| @ -0,0 +1,23 @@ | ||||
| #include "org_bitcoin_NativeSecp256k1.h" | ||||
| #include "include/secp256k1.h" | ||||
| 
 | ||||
| JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify | ||||
|   (JNIEnv* env, jclass classObject, jobject byteBufferObject) | ||||
| { | ||||
| 	unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||
| 	int sigLen = *((int*)(data + 32)); | ||||
| 	int pubLen = *((int*)(data + 32 + 4)); | ||||
| 
 | ||||
| 	return secp256k1_ecdsa_verify(data, 32, data+32+8, sigLen, data+32+8+sigLen, pubLen); | ||||
| } | ||||
| 
 | ||||
| static void __javasecp256k1_attach(void) __attribute__((constructor)); | ||||
| static void __javasecp256k1_detach(void) __attribute__((destructor)); | ||||
| 
 | ||||
| static void __javasecp256k1_attach(void) { | ||||
| 	secp256k1_start(); | ||||
| } | ||||
| 
 | ||||
| static void __javasecp256k1_detach(void) { | ||||
| 	secp256k1_stop(); | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| /* DO NOT EDIT THIS FILE - it is machine generated */ | ||||
| #include <jni.h> | ||||
| /* Header for class org_bitcoin_NativeSecp256k1 */ | ||||
| 
 | ||||
| #ifndef _Included_org_bitcoin_NativeSecp256k1 | ||||
| #define _Included_org_bitcoin_NativeSecp256k1 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| /*
 | ||||
|  * Class:     org_bitcoin_NativeSecp256k1 | ||||
|  * Method:    secp256k1_ecdsa_verify | ||||
|  * Signature: (Ljava/nio/ByteBuffer;)I | ||||
|  */ | ||||
| JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify | ||||
|   (JNIEnv *, jclass, jobject); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
							
								
								
									
										93
									
								
								crypto/secp256k1/secp256k1/src/num.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								crypto/secp256k1/secp256k1/src/num.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_NUM_ | ||||
| #define _SECP256K1_NUM_ | ||||
| 
 | ||||
| #if defined(USE_NUM_GMP) | ||||
| #include "num_gmp.h" | ||||
| #elif defined(USE_NUM_OPENSSL) | ||||
| #include "num_openssl.h" | ||||
| #else | ||||
| #error "Please select num implementation" | ||||
| #endif | ||||
| 
 | ||||
| /** Initialize a number. */ | ||||
| void static secp256k1_num_init(secp256k1_num_t *r); | ||||
| 
 | ||||
| /** Free a number. */ | ||||
| void static secp256k1_num_free(secp256k1_num_t *r); | ||||
| 
 | ||||
| /** Copy a number. */ | ||||
| void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a); | ||||
| 
 | ||||
| /** Convert a number's absolute value to a binary big-endian string.
 | ||||
|  *  There must be enough place. */ | ||||
| void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a); | ||||
| 
 | ||||
| /** Set a number to the value of a binary big-endian string. */ | ||||
| void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen); | ||||
| 
 | ||||
| /** Set a number equal to a (signed) integer. */ | ||||
| void static secp256k1_num_set_int(secp256k1_num_t *r, int a); | ||||
| 
 | ||||
| /** Compute a modular inverse. The input must be less than the modulus. */ | ||||
| void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m); | ||||
| 
 | ||||
| /** Multiply two numbers modulo another. */ | ||||
| void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m); | ||||
| 
 | ||||
| /** Compare the absolute value of two numbers. */ | ||||
| int  static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b); | ||||
| 
 | ||||
| /** Add two (signed) numbers. */ | ||||
| void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); | ||||
| 
 | ||||
| /** Subtract two (signed) numbers. */ | ||||
| void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); | ||||
| 
 | ||||
| /** Multiply two (signed) numbers. */ | ||||
| void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); | ||||
| 
 | ||||
| /** Divide two (signed) numbers. */ | ||||
| void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); | ||||
| 
 | ||||
| /** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1,
 | ||||
|     even if r was negative. */ | ||||
| void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m); | ||||
| 
 | ||||
| /** Calculate the number of bits in (the absolute value of) a number. */ | ||||
| int  static secp256k1_num_bits(const secp256k1_num_t *a); | ||||
| 
 | ||||
| /** Right-shift the passed number by bits bits, and return those bits. */ | ||||
| int  static secp256k1_num_shift(secp256k1_num_t *r, int bits); | ||||
| 
 | ||||
| /** Check whether a number is zero. */ | ||||
| int  static secp256k1_num_is_zero(const secp256k1_num_t *a); | ||||
| 
 | ||||
| /** Check whether a number is odd. */ | ||||
| int  static secp256k1_num_is_odd(const secp256k1_num_t *a); | ||||
| 
 | ||||
| /** Check whether a number is strictly negative. */ | ||||
| int  static secp256k1_num_is_neg(const secp256k1_num_t *a); | ||||
| 
 | ||||
| /** Check whether a particular bit is set in a number. */ | ||||
| int  static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos); | ||||
| 
 | ||||
| /** Increase a number by 1. */ | ||||
| void static secp256k1_num_inc(secp256k1_num_t *r); | ||||
| 
 | ||||
| /** Set a number equal to the value of a hex string (unsigned). */ | ||||
| void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen); | ||||
| 
 | ||||
| /** Convert (the absolute value of) a number to a hexadecimal string. */ | ||||
| void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a); | ||||
| 
 | ||||
| /** Split a number into a low and high part. */ | ||||
| void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits); | ||||
| 
 | ||||
| /** Change a number's sign. */ | ||||
| void static secp256k1_num_negate(secp256k1_num_t *r); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										18
									
								
								crypto/secp256k1/secp256k1/src/num_gmp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								crypto/secp256k1/secp256k1/src/num_gmp.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_NUM_REPR_ | ||||
| #define _SECP256K1_NUM_REPR_ | ||||
| 
 | ||||
| #include <gmp.h> | ||||
| 
 | ||||
| #define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS) | ||||
| 
 | ||||
| typedef struct { | ||||
|     mp_limb_t data[2*NUM_LIMBS]; | ||||
|     int neg; | ||||
|     int limbs; | ||||
| } secp256k1_num_t; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										14
									
								
								crypto/secp256k1/secp256k1/src/num_openssl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								crypto/secp256k1/secp256k1/src/num_openssl.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_NUM_REPR_ | ||||
| #define _SECP256K1_NUM_REPR_ | ||||
| 
 | ||||
| #include <openssl/bn.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|     BIGNUM bn; | ||||
| } secp256k1_num_t; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										269
									
								
								crypto/secp256k1/secp256k1/src/secp256k1.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								crypto/secp256k1/secp256k1/src/secp256k1.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,269 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #include "impl/num.h" | ||||
| #include "impl/field.h" | ||||
| #include "impl/group.h" | ||||
| #include "impl/ecmult.h" | ||||
| #include "impl/ecdsa.h" | ||||
| 
 | ||||
| void secp256k1_start(void) { | ||||
|     secp256k1_fe_start(); | ||||
|     secp256k1_ge_start(); | ||||
|     secp256k1_ecmult_start(); | ||||
| } | ||||
| 
 | ||||
| void secp256k1_stop(void) { | ||||
|     secp256k1_ecmult_stop(); | ||||
|     secp256k1_ge_stop(); | ||||
|     secp256k1_fe_stop(); | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) { | ||||
|     int ret = -3; | ||||
|     secp256k1_num_t m;  | ||||
|     secp256k1_num_init(&m); | ||||
|     secp256k1_ecdsa_sig_t s; | ||||
|     secp256k1_ecdsa_sig_init(&s); | ||||
|     secp256k1_ge_t q; | ||||
|     secp256k1_num_set_bin(&m, msg, msglen); | ||||
| 
 | ||||
|     if (!secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen)) { | ||||
|         ret = -1; | ||||
|         goto end; | ||||
|     } | ||||
|     if (!secp256k1_ecdsa_sig_parse(&s, sig, siglen)) { | ||||
|         ret = -2; | ||||
|         goto end; | ||||
|     } | ||||
|     if (!secp256k1_ecdsa_sig_verify(&s, &q, &m)) { | ||||
|         ret = 0; | ||||
|         goto end; | ||||
|     } | ||||
|     ret = 1; | ||||
| end: | ||||
|     secp256k1_ecdsa_sig_free(&s); | ||||
|     secp256k1_num_free(&m); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) { | ||||
|     secp256k1_num_t sec, non, msg; | ||||
|     secp256k1_num_init(&sec); | ||||
|     secp256k1_num_init(&non); | ||||
|     secp256k1_num_init(&msg); | ||||
|     secp256k1_num_set_bin(&sec, seckey, 32); | ||||
|     secp256k1_num_set_bin(&non, nonce, 32); | ||||
|     secp256k1_num_set_bin(&msg, message, messagelen); | ||||
|     secp256k1_ecdsa_sig_t sig; | ||||
|     secp256k1_ecdsa_sig_init(&sig); | ||||
|     int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL); | ||||
|     if (ret) { | ||||
|         secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig); | ||||
|     } | ||||
|     secp256k1_ecdsa_sig_free(&sig); | ||||
|     secp256k1_num_free(&msg); | ||||
|     secp256k1_num_free(&non); | ||||
|     secp256k1_num_free(&sec); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) { | ||||
|     secp256k1_num_t sec, non, msg; | ||||
|     secp256k1_num_init(&sec); | ||||
|     secp256k1_num_init(&non); | ||||
|     secp256k1_num_init(&msg); | ||||
|     secp256k1_num_set_bin(&sec, seckey, 32); | ||||
|     secp256k1_num_set_bin(&non, nonce, 32); | ||||
|     secp256k1_num_set_bin(&msg, message, messagelen); | ||||
|     secp256k1_ecdsa_sig_t sig; | ||||
|     secp256k1_ecdsa_sig_init(&sig); | ||||
|     int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid); | ||||
|     if (ret) { | ||||
|         secp256k1_num_get_bin(sig64, 32, &sig.r); | ||||
|         secp256k1_num_get_bin(sig64 + 32, 32, &sig.s); | ||||
|     } | ||||
|     secp256k1_ecdsa_sig_free(&sig); | ||||
|     secp256k1_num_free(&msg); | ||||
|     secp256k1_num_free(&non); | ||||
|     secp256k1_num_free(&sec); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) { | ||||
|     int ret = 0; | ||||
|     secp256k1_num_t m;  | ||||
|     secp256k1_num_init(&m); | ||||
|     secp256k1_ecdsa_sig_t sig; | ||||
|     secp256k1_ecdsa_sig_init(&sig); | ||||
|     secp256k1_num_set_bin(&sig.r, sig64, 32); | ||||
|     secp256k1_num_set_bin(&sig.s, sig64 + 32, 32); | ||||
|     secp256k1_num_set_bin(&m, msg, msglen); | ||||
| 
 | ||||
|     secp256k1_ge_t q; | ||||
|     if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) { | ||||
|         secp256k1_ecdsa_pubkey_serialize(&q, pubkey, pubkeylen, compressed); | ||||
|         ret = 1; | ||||
|     } | ||||
|     secp256k1_ecdsa_sig_free(&sig); | ||||
|     secp256k1_num_free(&m); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey) { | ||||
|     secp256k1_num_t sec; | ||||
|     secp256k1_num_init(&sec); | ||||
|     secp256k1_num_set_bin(&sec, seckey, 32); | ||||
|     int ret = !secp256k1_num_is_zero(&sec) && | ||||
|               (secp256k1_num_cmp(&sec, &secp256k1_ge_consts->order) < 0); | ||||
|     secp256k1_num_free(&sec); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { | ||||
|     secp256k1_ge_t q; | ||||
|     return secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen); | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { | ||||
|     secp256k1_num_t sec; | ||||
|     secp256k1_num_init(&sec); | ||||
|     secp256k1_num_set_bin(&sec, seckey, 32); | ||||
|     secp256k1_gej_t pj; | ||||
|     secp256k1_ecmult_gen(&pj, &sec); | ||||
|     secp256k1_ge_t p; | ||||
|     secp256k1_ge_set_gej(&p, &pj); | ||||
|     secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed); | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { | ||||
|     secp256k1_ge_t p; | ||||
|     if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, *pubkeylen)) | ||||
|         return 0; | ||||
|     secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, 0); | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) { | ||||
|     int ret = 1; | ||||
|     secp256k1_num_t term; | ||||
|     secp256k1_num_init(&term); | ||||
|     secp256k1_num_set_bin(&term, tweak, 32); | ||||
|     if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0) | ||||
|         ret = 0; | ||||
|     secp256k1_num_t sec; | ||||
|     secp256k1_num_init(&sec); | ||||
|     if (ret) { | ||||
|         secp256k1_num_set_bin(&sec, seckey, 32); | ||||
|         secp256k1_num_add(&sec, &sec, &term); | ||||
|         secp256k1_num_mod(&sec, &secp256k1_ge_consts->order); | ||||
|         if (secp256k1_num_is_zero(&sec)) | ||||
|             ret = 0; | ||||
|     } | ||||
|     if (ret) | ||||
|         secp256k1_num_get_bin(seckey, 32, &sec); | ||||
|     secp256k1_num_free(&sec); | ||||
|     secp256k1_num_free(&term); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { | ||||
|     int ret = 1; | ||||
|     secp256k1_num_t term; | ||||
|     secp256k1_num_init(&term); | ||||
|     secp256k1_num_set_bin(&term, tweak, 32); | ||||
|     if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0) | ||||
|         ret = 0; | ||||
|     secp256k1_ge_t p; | ||||
|     if (ret) { | ||||
|         if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) | ||||
|             ret = 0; | ||||
|     } | ||||
|     if (ret) { | ||||
|         secp256k1_gej_t pt; | ||||
|         secp256k1_ecmult_gen(&pt, &term); | ||||
|         secp256k1_gej_add_ge(&pt, &pt, &p); | ||||
|         if (secp256k1_gej_is_infinity(&pt)) | ||||
|             ret = 0; | ||||
|         secp256k1_ge_set_gej(&p, &pt); | ||||
|         int oldlen = pubkeylen; | ||||
|         secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); | ||||
|         assert(pubkeylen == oldlen); | ||||
|     } | ||||
|     secp256k1_num_free(&term); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) { | ||||
|     int ret = 1; | ||||
|     secp256k1_num_t factor; | ||||
|     secp256k1_num_init(&factor); | ||||
|     secp256k1_num_set_bin(&factor, tweak, 32); | ||||
|     if (secp256k1_num_is_zero(&factor)) | ||||
|         ret = 0; | ||||
|     if (secp256k1_num_cmp(&factor, &secp256k1_ge_consts->order) >= 0) | ||||
|         ret = 0; | ||||
|     secp256k1_num_t sec; | ||||
|     secp256k1_num_init(&sec); | ||||
|     if (ret) { | ||||
|         secp256k1_num_set_bin(&sec, seckey, 32); | ||||
|         secp256k1_num_mod_mul(&sec, &sec, &factor, &secp256k1_ge_consts->order); | ||||
|     } | ||||
|     if (ret) | ||||
|         secp256k1_num_get_bin(seckey, 32, &sec); | ||||
|     secp256k1_num_free(&sec); | ||||
|     secp256k1_num_free(&factor); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { | ||||
|     int ret = 1; | ||||
|     secp256k1_num_t factor; | ||||
|     secp256k1_num_init(&factor); | ||||
|     secp256k1_num_set_bin(&factor, tweak, 32); | ||||
|     if (secp256k1_num_is_zero(&factor)) | ||||
|         ret = 0; | ||||
|     if (secp256k1_num_cmp(&factor, &secp256k1_ge_consts->order) >= 0) | ||||
|         ret = 0; | ||||
|     secp256k1_ge_t p; | ||||
|     if (ret) { | ||||
|         if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen)) | ||||
|             ret = 0; | ||||
|     } | ||||
|     if (ret) { | ||||
|         secp256k1_num_t zero; | ||||
|         secp256k1_num_init(&zero); | ||||
|         secp256k1_num_set_int(&zero, 0); | ||||
|         secp256k1_gej_t pt; | ||||
|         secp256k1_gej_set_ge(&pt, &p); | ||||
|         secp256k1_ecmult(&pt, &pt, &factor, &zero); | ||||
|         secp256k1_num_free(&zero); | ||||
|         secp256k1_ge_set_gej(&p, &pt); | ||||
|         int oldlen = pubkeylen; | ||||
|         secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); | ||||
|         assert(pubkeylen == oldlen); | ||||
|     } | ||||
|     secp256k1_num_free(&factor); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) { | ||||
|     secp256k1_num_t key; | ||||
|     secp256k1_num_init(&key); | ||||
|     secp256k1_num_set_bin(&key, seckey, 32); | ||||
|     int ret = secp256k1_ecdsa_privkey_serialize(privkey, privkeylen, &key, compressed); | ||||
|     secp256k1_num_free(&key); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| int secp256k1_ecdsa_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) { | ||||
|     secp256k1_num_t key; | ||||
|     secp256k1_num_init(&key); | ||||
|     int ret = secp256k1_ecdsa_privkey_parse(&key, privkey, privkeylen); | ||||
|     if (ret) | ||||
|         secp256k1_num_get_bin(seckey, 32, &key); | ||||
|     secp256k1_num_free(&key); | ||||
|     return ret; | ||||
| } | ||||
							
								
								
									
										465
									
								
								crypto/secp256k1/secp256k1/src/tests.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										465
									
								
								crypto/secp256k1/secp256k1/src/tests.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,465 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #include "impl/num.h" | ||||
| #include "impl/field.h" | ||||
| #include "impl/group.h" | ||||
| #include "impl/ecmult.h" | ||||
| #include "impl/ecdsa.h" | ||||
| #include "impl/util.h" | ||||
| 
 | ||||
| #ifdef ENABLE_OPENSSL_TESTS | ||||
| #include "openssl/bn.h" | ||||
| #include "openssl/ec.h" | ||||
| #include "openssl/ecdsa.h" | ||||
| #include "openssl/obj_mac.h" | ||||
| #endif | ||||
| 
 | ||||
| static int count = 100; | ||||
| 
 | ||||
| /***** NUM TESTS *****/ | ||||
| 
 | ||||
| void random_num_negate(secp256k1_num_t *num) { | ||||
|     if (secp256k1_rand32() & 1) | ||||
|         secp256k1_num_negate(num); | ||||
| } | ||||
| 
 | ||||
| void random_num_order_test(secp256k1_num_t *num) { | ||||
|     do { | ||||
|         unsigned char b32[32]; | ||||
|         secp256k1_rand256_test(b32); | ||||
|         secp256k1_num_set_bin(num, b32, 32); | ||||
|         if (secp256k1_num_is_zero(num)) | ||||
|             continue; | ||||
|         if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0) | ||||
|             continue; | ||||
|         break; | ||||
|     } while(1); | ||||
| } | ||||
| 
 | ||||
| void random_num_order(secp256k1_num_t *num) { | ||||
|     do { | ||||
|         unsigned char b32[32]; | ||||
|         secp256k1_rand256(b32); | ||||
|         secp256k1_num_set_bin(num, b32, 32); | ||||
|         if (secp256k1_num_is_zero(num)) | ||||
|             continue; | ||||
|         if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0) | ||||
|             continue; | ||||
|         break; | ||||
|     } while(1); | ||||
| } | ||||
| 
 | ||||
| void test_num_copy_inc_cmp() { | ||||
|     secp256k1_num_t n1,n2; | ||||
|     secp256k1_num_init(&n1); | ||||
|     secp256k1_num_init(&n2); | ||||
|     random_num_order(&n1); | ||||
|     secp256k1_num_copy(&n2, &n1); | ||||
|     assert(secp256k1_num_cmp(&n1, &n2) == 0); | ||||
|     assert(secp256k1_num_cmp(&n2, &n1) == 0); | ||||
|     secp256k1_num_inc(&n2); | ||||
|     assert(secp256k1_num_cmp(&n1, &n2) != 0); | ||||
|     assert(secp256k1_num_cmp(&n2, &n1) != 0); | ||||
|     secp256k1_num_free(&n1); | ||||
|     secp256k1_num_free(&n2); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void test_num_get_set_hex() { | ||||
|     secp256k1_num_t n1,n2; | ||||
|     secp256k1_num_init(&n1); | ||||
|     secp256k1_num_init(&n2); | ||||
|     random_num_order_test(&n1); | ||||
|     char c[64]; | ||||
|     secp256k1_num_get_hex(c, 64, &n1); | ||||
|     secp256k1_num_set_hex(&n2, c, 64); | ||||
|     assert(secp256k1_num_cmp(&n1, &n2) == 0); | ||||
|     for (int i=0; i<64; i++) { | ||||
|         // check whether the lower 4 bits correspond to the last hex character
 | ||||
|         int low1 = secp256k1_num_shift(&n1, 4); | ||||
|         int lowh = c[63]; | ||||
|         int low2 = (lowh>>6)*9+(lowh-'0')&15; | ||||
|         assert(low1 == low2); | ||||
|         // shift bits off the hex representation, and compare
 | ||||
|         memmove(c+1, c, 63); | ||||
|         c[0] = '0'; | ||||
|         secp256k1_num_set_hex(&n2, c, 64); | ||||
|         assert(secp256k1_num_cmp(&n1, &n2) == 0); | ||||
|     } | ||||
|     secp256k1_num_free(&n2); | ||||
|     secp256k1_num_free(&n1); | ||||
| } | ||||
| 
 | ||||
| void test_num_get_set_bin() { | ||||
|     secp256k1_num_t n1,n2; | ||||
|     secp256k1_num_init(&n1); | ||||
|     secp256k1_num_init(&n2); | ||||
|     random_num_order_test(&n1); | ||||
|     unsigned char c[32]; | ||||
|     secp256k1_num_get_bin(c, 32, &n1); | ||||
|     secp256k1_num_set_bin(&n2, c, 32); | ||||
|     assert(secp256k1_num_cmp(&n1, &n2) == 0); | ||||
|     for (int i=0; i<32; i++) { | ||||
|         // check whether the lower 8 bits correspond to the last byte
 | ||||
|         int low1 = secp256k1_num_shift(&n1, 8); | ||||
|         int low2 = c[31]; | ||||
|         assert(low1 == low2); | ||||
|         // shift bits off the byte representation, and compare
 | ||||
|         memmove(c+1, c, 31); | ||||
|         c[0] = 0; | ||||
|         secp256k1_num_set_bin(&n2, c, 32); | ||||
|         assert(secp256k1_num_cmp(&n1, &n2) == 0); | ||||
|     } | ||||
|     secp256k1_num_free(&n2); | ||||
|     secp256k1_num_free(&n1); | ||||
| } | ||||
| 
 | ||||
| void run_num_int() { | ||||
|     secp256k1_num_t n1; | ||||
|     secp256k1_num_init(&n1); | ||||
|     for (int i=-255; i<256; i++) { | ||||
|         unsigned char c1[3] = {}; | ||||
|         c1[2] = abs(i); | ||||
|         unsigned char c2[3] = {0x11,0x22,0x33}; | ||||
|         secp256k1_num_set_int(&n1, i); | ||||
|         secp256k1_num_get_bin(c2, 3, &n1); | ||||
|         assert(memcmp(c1, c2, 3) == 0); | ||||
|     } | ||||
|     secp256k1_num_free(&n1); | ||||
| } | ||||
| 
 | ||||
| void test_num_negate() { | ||||
|     secp256k1_num_t n1; | ||||
|     secp256k1_num_t n2; | ||||
|     secp256k1_num_init(&n1); | ||||
|     secp256k1_num_init(&n2); | ||||
|     random_num_order_test(&n1); // n1 = R
 | ||||
|     random_num_negate(&n1); | ||||
|     secp256k1_num_copy(&n2, &n1); // n2 = R
 | ||||
|     secp256k1_num_sub(&n1, &n2, &n1); // n1 = n2-n1 = 0
 | ||||
|     assert(secp256k1_num_is_zero(&n1)); | ||||
|     secp256k1_num_copy(&n1, &n2); // n1 = R
 | ||||
|     secp256k1_num_negate(&n1); // n1 = -R
 | ||||
|     assert(!secp256k1_num_is_zero(&n1)); | ||||
|     secp256k1_num_add(&n1, &n2, &n1); // n1 = n2+n1 = 0
 | ||||
|     assert(secp256k1_num_is_zero(&n1)); | ||||
|     secp256k1_num_copy(&n1, &n2); // n1 = R
 | ||||
|     secp256k1_num_negate(&n1); // n1 = -R
 | ||||
|     assert(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2)); | ||||
|     secp256k1_num_negate(&n1); // n1 = R
 | ||||
|     assert(secp256k1_num_cmp(&n1, &n2) == 0); | ||||
|     assert(secp256k1_num_is_neg(&n1) == secp256k1_num_is_neg(&n2)); | ||||
|     secp256k1_num_free(&n2); | ||||
|     secp256k1_num_free(&n1); | ||||
| } | ||||
| 
 | ||||
| void test_num_add_sub() { | ||||
|     secp256k1_num_t n1; | ||||
|     secp256k1_num_t n2; | ||||
|     secp256k1_num_init(&n1); | ||||
|     secp256k1_num_init(&n2); | ||||
|     random_num_order_test(&n1); // n1 = R1
 | ||||
|     random_num_negate(&n1); | ||||
|     random_num_order_test(&n2); // n2 = R2
 | ||||
|     random_num_negate(&n2); | ||||
|     secp256k1_num_t n1p2, n2p1, n1m2, n2m1; | ||||
|     secp256k1_num_init(&n1p2); | ||||
|     secp256k1_num_init(&n2p1); | ||||
|     secp256k1_num_init(&n1m2); | ||||
|     secp256k1_num_init(&n2m1); | ||||
|     secp256k1_num_add(&n1p2, &n1, &n2); // n1p2 = R1 + R2
 | ||||
|     secp256k1_num_add(&n2p1, &n2, &n1); // n2p1 = R2 + R1
 | ||||
|     secp256k1_num_sub(&n1m2, &n1, &n2); // n1m2 = R1 - R2
 | ||||
|     secp256k1_num_sub(&n2m1, &n2, &n1); // n2m1 = R2 - R1
 | ||||
|     assert(secp256k1_num_cmp(&n1p2, &n2p1) == 0); | ||||
|     assert(secp256k1_num_cmp(&n1p2, &n1m2) != 0); | ||||
|     secp256k1_num_negate(&n2m1); // n2m1 = -R2 + R1
 | ||||
|     assert(secp256k1_num_cmp(&n2m1, &n1m2) == 0); | ||||
|     assert(secp256k1_num_cmp(&n2m1, &n1) != 0); | ||||
|     secp256k1_num_add(&n2m1, &n2m1, &n2); // n2m1 = -R2 + R1 + R2 = R1
 | ||||
|     assert(secp256k1_num_cmp(&n2m1, &n1) == 0); | ||||
|     assert(secp256k1_num_cmp(&n2p1, &n1) != 0); | ||||
|     secp256k1_num_sub(&n2p1, &n2p1, &n2); // n2p1 = R2 + R1 - R2 = R1
 | ||||
|     assert(secp256k1_num_cmp(&n2p1, &n1) == 0); | ||||
|     secp256k1_num_free(&n2m1); | ||||
|     secp256k1_num_free(&n1m2); | ||||
|     secp256k1_num_free(&n2p1); | ||||
|     secp256k1_num_free(&n1p2); | ||||
|     secp256k1_num_free(&n2); | ||||
|     secp256k1_num_free(&n1); | ||||
| } | ||||
| 
 | ||||
| void run_num_smalltests() { | ||||
|     for (int i=0; i<100*count; i++) { | ||||
|         test_num_copy_inc_cmp(); | ||||
|         test_num_get_set_hex(); | ||||
|         test_num_get_set_bin(); | ||||
|         test_num_negate(); | ||||
|         test_num_add_sub(); | ||||
|     } | ||||
|     run_num_int(); | ||||
| } | ||||
| 
 | ||||
| void run_ecmult_chain() { | ||||
|     // random starting point A (on the curve)
 | ||||
|     secp256k1_fe_t ax; secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64); | ||||
|     secp256k1_fe_t ay; secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64); | ||||
|     secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay); | ||||
|     // two random initial factors xn and gn
 | ||||
|     secp256k1_num_t xn; | ||||
|     secp256k1_num_init(&xn); | ||||
|     secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64); | ||||
|     secp256k1_num_t gn; | ||||
|     secp256k1_num_init(&gn); | ||||
|     secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64); | ||||
|     // two small multipliers to be applied to xn and gn in every iteration:
 | ||||
|     secp256k1_num_t xf; | ||||
|     secp256k1_num_init(&xf); | ||||
|     secp256k1_num_set_hex(&xf, "1337", 4); | ||||
|     secp256k1_num_t gf; | ||||
|     secp256k1_num_init(&gf); | ||||
|     secp256k1_num_set_hex(&gf, "7113", 4); | ||||
|     // accumulators with the resulting coefficients to A and G
 | ||||
|     secp256k1_num_t ae; | ||||
|     secp256k1_num_init(&ae); | ||||
|     secp256k1_num_set_int(&ae, 1); | ||||
|     secp256k1_num_t ge; | ||||
|     secp256k1_num_init(&ge); | ||||
|     secp256k1_num_set_int(&ge, 0); | ||||
|     // the point being computed
 | ||||
|     secp256k1_gej_t x = a; | ||||
|     const secp256k1_num_t *order = &secp256k1_ge_consts->order; | ||||
|     for (int i=0; i<200*count; i++) { | ||||
|         // in each iteration, compute X = xn*X + gn*G;
 | ||||
|         secp256k1_ecmult(&x, &x, &xn, &gn); | ||||
|         // also compute ae and ge: the actual accumulated factors for A and G
 | ||||
|         // if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G)
 | ||||
|         secp256k1_num_mod_mul(&ae, &ae, &xn, order); | ||||
|         secp256k1_num_mod_mul(&ge, &ge, &xn, order); | ||||
|         secp256k1_num_add(&ge, &ge, &gn); | ||||
|         secp256k1_num_mod(&ge, order); | ||||
|         // modify xn and gn
 | ||||
|         secp256k1_num_mod_mul(&xn, &xn, &xf, order); | ||||
|         secp256k1_num_mod_mul(&gn, &gn, &gf, order); | ||||
| 
 | ||||
|         // verify
 | ||||
|         if (i == 19999) { | ||||
|             char res[132]; int resl = 132; | ||||
|             secp256k1_gej_get_hex(res, &resl, &x); | ||||
|             assert(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0); | ||||
|         } | ||||
|     } | ||||
|     // redo the computation, but directly with the resulting ae and ge coefficients:
 | ||||
|     secp256k1_gej_t x2; secp256k1_ecmult(&x2, &a, &ae, &ge); | ||||
|     char res[132]; int resl = 132; | ||||
|     char res2[132]; int resl2 = 132; | ||||
|     secp256k1_gej_get_hex(res, &resl, &x); | ||||
|     secp256k1_gej_get_hex(res2, &resl2, &x2); | ||||
|     assert(strcmp(res, res2) == 0); | ||||
|     assert(strlen(res) == 131); | ||||
|     secp256k1_num_free(&xn); | ||||
|     secp256k1_num_free(&gn); | ||||
|     secp256k1_num_free(&xf); | ||||
|     secp256k1_num_free(&gf); | ||||
|     secp256k1_num_free(&ae); | ||||
|     secp256k1_num_free(&ge); | ||||
| } | ||||
| 
 | ||||
| void test_point_times_order(const secp256k1_gej_t *point) { | ||||
|     // either the point is not on the curve, or multiplying it by the order results in O
 | ||||
|     if (!secp256k1_gej_is_valid(point)) | ||||
|         return; | ||||
| 
 | ||||
|     const secp256k1_num_t *order = &secp256k1_ge_consts->order; | ||||
|     secp256k1_num_t zero; | ||||
|     secp256k1_num_init(&zero); | ||||
|     secp256k1_num_set_int(&zero, 0); | ||||
|     secp256k1_gej_t res; | ||||
|     secp256k1_ecmult(&res, point, order, order); // calc res = order * point + order * G;
 | ||||
|     assert(secp256k1_gej_is_infinity(&res)); | ||||
|     secp256k1_num_free(&zero); | ||||
| } | ||||
| 
 | ||||
| void run_point_times_order() { | ||||
|     secp256k1_fe_t x; secp256k1_fe_set_hex(&x, "02", 2); | ||||
|     for (int i=0; i<500; i++) { | ||||
|         secp256k1_ge_t p; secp256k1_ge_set_xo(&p, &x, 1); | ||||
|         secp256k1_gej_t j; secp256k1_gej_set_ge(&j, &p); | ||||
|         test_point_times_order(&j); | ||||
|         secp256k1_fe_sqr(&x, &x); | ||||
|     } | ||||
|     char c[65]; int cl=65; | ||||
|     secp256k1_fe_get_hex(c, &cl, &x); | ||||
|     assert(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0); | ||||
| } | ||||
| 
 | ||||
| void test_wnaf(const secp256k1_num_t *number, int w) { | ||||
|     secp256k1_num_t x, two, t; | ||||
|     secp256k1_num_init(&x); | ||||
|     secp256k1_num_init(&two); | ||||
|     secp256k1_num_init(&t); | ||||
|     secp256k1_num_set_int(&x, 0); | ||||
|     secp256k1_num_set_int(&two, 2); | ||||
|     int wnaf[257]; | ||||
|     int bits = secp256k1_ecmult_wnaf(wnaf, number, w); | ||||
|     int zeroes = -1; | ||||
|     for (int i=bits-1; i>=0; i--) { | ||||
|         secp256k1_num_mul(&x, &x, &two); | ||||
|         int v = wnaf[i]; | ||||
|         if (v) { | ||||
|             assert(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
 | ||||
|             zeroes=0; | ||||
|             assert((v & 1) == 1); // check non-zero elements are odd
 | ||||
|             assert(v <= (1 << (w-1)) - 1); // check range below
 | ||||
|             assert(v >= -(1 << (w-1)) - 1); // check range above
 | ||||
|         } else { | ||||
|             assert(zeroes != -1); // check that no unnecessary zero padding exists
 | ||||
|             zeroes++; | ||||
|         } | ||||
|         secp256k1_num_set_int(&t, v); | ||||
|         secp256k1_num_add(&x, &x, &t); | ||||
|     } | ||||
|     assert(secp256k1_num_cmp(&x, number) == 0); // check that wnaf represents number
 | ||||
|     secp256k1_num_free(&x); | ||||
|     secp256k1_num_free(&two); | ||||
|     secp256k1_num_free(&t); | ||||
| } | ||||
| 
 | ||||
| void run_wnaf() { | ||||
|     secp256k1_num_t n; | ||||
|     secp256k1_num_init(&n); | ||||
|     for (int i=0; i<count; i++) { | ||||
|         random_num_order(&n); | ||||
|         if (i % 1) | ||||
|             secp256k1_num_negate(&n); | ||||
|         test_wnaf(&n, 4+(i%10)); | ||||
|     } | ||||
|     secp256k1_num_free(&n); | ||||
| } | ||||
| 
 | ||||
| void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *key, const secp256k1_num_t *msg, int *recid) { | ||||
|     secp256k1_num_t nonce; | ||||
|     secp256k1_num_init(&nonce); | ||||
|     do { | ||||
|         random_num_order_test(&nonce); | ||||
|     } while(!secp256k1_ecdsa_sig_sign(sig, key, msg, &nonce, recid)); | ||||
|     secp256k1_num_free(&nonce); | ||||
| } | ||||
| 
 | ||||
| void test_ecdsa_sign_verify() { | ||||
|     const secp256k1_ge_consts_t *c = secp256k1_ge_consts; | ||||
|     secp256k1_num_t msg, key; | ||||
|     secp256k1_num_init(&msg); | ||||
|     random_num_order_test(&msg); | ||||
|     secp256k1_num_init(&key); | ||||
|     random_num_order_test(&key); | ||||
|     secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key); | ||||
|     secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj); | ||||
|     secp256k1_ecdsa_sig_t sig; | ||||
|     secp256k1_ecdsa_sig_init(&sig); | ||||
|     random_sign(&sig, &key, &msg, NULL); | ||||
|     assert(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg)); | ||||
|     secp256k1_num_inc(&msg); | ||||
|     assert(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg)); | ||||
|     secp256k1_ecdsa_sig_free(&sig); | ||||
|     secp256k1_num_free(&msg); | ||||
|     secp256k1_num_free(&key); | ||||
| } | ||||
| 
 | ||||
| void run_ecdsa_sign_verify() { | ||||
|     for (int i=0; i<10*count; i++) { | ||||
|         test_ecdsa_sign_verify(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #ifdef ENABLE_OPENSSL_TESTS | ||||
| EC_KEY *get_openssl_key(const secp256k1_num_t *key) { | ||||
|     unsigned char privkey[300]; | ||||
|     int privkeylen; | ||||
|     int compr = secp256k1_rand32() & 1; | ||||
|     const unsigned char* pbegin = privkey; | ||||
|     EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); | ||||
|     assert(secp256k1_ecdsa_privkey_serialize(privkey, &privkeylen, key, compr)); | ||||
|     assert(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); | ||||
|     assert(EC_KEY_check_key(ec_key)); | ||||
|     return ec_key; | ||||
| } | ||||
| 
 | ||||
| void test_ecdsa_openssl() { | ||||
|     const secp256k1_ge_consts_t *c = secp256k1_ge_consts; | ||||
|     secp256k1_num_t key, msg; | ||||
|     secp256k1_num_init(&msg); | ||||
|     unsigned char message[32]; | ||||
|     secp256k1_rand256_test(message); | ||||
|     secp256k1_num_set_bin(&msg, message, 32); | ||||
|     secp256k1_num_init(&key); | ||||
|     random_num_order_test(&key); | ||||
|     secp256k1_gej_t qj; | ||||
|     secp256k1_ecmult_gen(&qj, &key); | ||||
|     secp256k1_ge_t q; | ||||
|     secp256k1_ge_set_gej(&q, &qj); | ||||
|     EC_KEY *ec_key = get_openssl_key(&key); | ||||
|     assert(ec_key); | ||||
|     unsigned char signature[80]; | ||||
|     int sigsize = 80; | ||||
|     assert(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); | ||||
|     secp256k1_ecdsa_sig_t sig; | ||||
|     secp256k1_ecdsa_sig_init(&sig); | ||||
|     assert(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize)); | ||||
|     assert(secp256k1_ecdsa_sig_verify(&sig, &q, &msg)); | ||||
|     secp256k1_num_inc(&sig.r); | ||||
|     assert(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg)); | ||||
| 
 | ||||
|     random_sign(&sig, &key, &msg, NULL); | ||||
|     sigsize = 80; | ||||
|     assert(secp256k1_ecdsa_sig_serialize(signature, &sigsize, &sig)); | ||||
|     assert(ECDSA_verify(0, message, sizeof(message), signature, sigsize, ec_key) == 1); | ||||
| 
 | ||||
|     secp256k1_ecdsa_sig_free(&sig); | ||||
|     EC_KEY_free(ec_key); | ||||
|     secp256k1_num_free(&key); | ||||
|     secp256k1_num_free(&msg); | ||||
| } | ||||
| 
 | ||||
| void run_ecdsa_openssl() { | ||||
|     for (int i=0; i<10*count; i++) { | ||||
|         test_ecdsa_openssl(); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| int main(int argc, char **argv) { | ||||
|     if (argc > 1) | ||||
|         count = strtol(argv[1], NULL, 0)*47; | ||||
| 
 | ||||
|     printf("test count = %i\n", count); | ||||
| 
 | ||||
|     // initialize
 | ||||
|     secp256k1_fe_start(); | ||||
|     secp256k1_ge_start(); | ||||
|     secp256k1_ecmult_start(); | ||||
| 
 | ||||
|     // num tests
 | ||||
|     run_num_smalltests(); | ||||
| 
 | ||||
|     // ecmult tests
 | ||||
|     run_wnaf(); | ||||
|     run_point_times_order(); | ||||
|     run_ecmult_chain(); | ||||
| 
 | ||||
|     // ecdsa tests
 | ||||
|     run_ecdsa_sign_verify(); | ||||
| #ifdef ENABLE_OPENSSL_TESTS | ||||
|     run_ecdsa_openssl(); | ||||
| #endif | ||||
| 
 | ||||
|     // shutdown
 | ||||
|     secp256k1_ecmult_stop(); | ||||
|     secp256k1_ge_stop(); | ||||
|     secp256k1_fe_stop(); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										19
									
								
								crypto/secp256k1/secp256k1/src/util.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								crypto/secp256k1/secp256k1/src/util.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // Copyright (c) 2013 Pieter Wuille
 | ||||
| // Distributed under the MIT/X11 software license, see the accompanying
 | ||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | ||||
| 
 | ||||
| #ifndef _SECP256K1_UTIL_H_ | ||||
| #define _SECP256K1_UTIL_H_ | ||||
| 
 | ||||
| /** Generate a pseudorandom 32-bit number. */ | ||||
| static uint32_t secp256k1_rand32(void); | ||||
| 
 | ||||
| /** Generate a pseudorandom 32-byte array. */ | ||||
| static void secp256k1_rand256(unsigned char *b32); | ||||
| 
 | ||||
| /** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ | ||||
| static void secp256k1_rand256_test(unsigned char *b32); | ||||
| 
 | ||||
| #include "impl/util.h" | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										171
									
								
								crypto/sha3/keccakf.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								crypto/sha3/keccakf.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,171 @@ | ||||
| // Copyright 2013 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| package sha3 | ||||
| 
 | ||||
| // This file implements the core Keccak permutation function necessary for computing SHA3.
 | ||||
| // This is implemented in a separate file to allow for replacement by an optimized implementation.
 | ||||
| // Nothing in this package is exported.
 | ||||
| // For the detailed specification, refer to the Keccak web site (http://keccak.noekeon.org/).
 | ||||
| 
 | ||||
| // rc stores the round constants for use in the ι step.
 | ||||
| var rc = [...]uint64{ | ||||
|         0x0000000000000001, | ||||
|         0x0000000000008082, | ||||
|         0x800000000000808A, | ||||
|         0x8000000080008000, | ||||
|         0x000000000000808B, | ||||
|         0x0000000080000001, | ||||
|         0x8000000080008081, | ||||
|         0x8000000000008009, | ||||
|         0x000000000000008A, | ||||
|         0x0000000000000088, | ||||
|         0x0000000080008009, | ||||
|         0x000000008000000A, | ||||
|         0x000000008000808B, | ||||
|         0x800000000000008B, | ||||
|         0x8000000000008089, | ||||
|         0x8000000000008003, | ||||
|         0x8000000000008002, | ||||
|         0x8000000000000080, | ||||
|         0x000000000000800A, | ||||
|         0x800000008000000A, | ||||
|         0x8000000080008081, | ||||
|         0x8000000000008080, | ||||
|         0x0000000080000001, | ||||
|         0x8000000080008008, | ||||
| } | ||||
| 
 | ||||
| // ro_xx represent the rotation offsets for use in the χ step.
 | ||||
| // Defining them as const instead of in an array allows the compiler to insert constant shifts.
 | ||||
| const ( | ||||
|         ro_00 = 0 | ||||
|         ro_01 = 36 | ||||
|         ro_02 = 3 | ||||
|         ro_03 = 41 | ||||
|         ro_04 = 18 | ||||
|         ro_05 = 1 | ||||
|         ro_06 = 44 | ||||
|         ro_07 = 10 | ||||
|         ro_08 = 45 | ||||
|         ro_09 = 2 | ||||
|         ro_10 = 62 | ||||
|         ro_11 = 6 | ||||
|         ro_12 = 43 | ||||
|         ro_13 = 15 | ||||
|         ro_14 = 61 | ||||
|         ro_15 = 28 | ||||
|         ro_16 = 55 | ||||
|         ro_17 = 25 | ||||
|         ro_18 = 21 | ||||
|         ro_19 = 56 | ||||
|         ro_20 = 27 | ||||
|         ro_21 = 20 | ||||
|         ro_22 = 39 | ||||
|         ro_23 = 8 | ||||
|         ro_24 = 14 | ||||
| ) | ||||
| 
 | ||||
| // keccakF computes the complete Keccak-f function consisting of 24 rounds with a different
 | ||||
| // constant (rc) in each round. This implementation fully unrolls the round function to avoid
 | ||||
| // inner loops, as well as pre-calculating shift offsets.
 | ||||
| func (d *digest) keccakF() { | ||||
|         for _, roundConstant := range rc { | ||||
|                 // θ step
 | ||||
|                 d.c[0] = d.a[0] ^ d.a[5] ^ d.a[10] ^ d.a[15] ^ d.a[20] | ||||
|                 d.c[1] = d.a[1] ^ d.a[6] ^ d.a[11] ^ d.a[16] ^ d.a[21] | ||||
|                 d.c[2] = d.a[2] ^ d.a[7] ^ d.a[12] ^ d.a[17] ^ d.a[22] | ||||
|                 d.c[3] = d.a[3] ^ d.a[8] ^ d.a[13] ^ d.a[18] ^ d.a[23] | ||||
|                 d.c[4] = d.a[4] ^ d.a[9] ^ d.a[14] ^ d.a[19] ^ d.a[24] | ||||
| 
 | ||||
|                 d.d[0] = d.c[4] ^ (d.c[1]<<1 ^ d.c[1]>>63) | ||||
|                 d.d[1] = d.c[0] ^ (d.c[2]<<1 ^ d.c[2]>>63) | ||||
|                 d.d[2] = d.c[1] ^ (d.c[3]<<1 ^ d.c[3]>>63) | ||||
|                 d.d[3] = d.c[2] ^ (d.c[4]<<1 ^ d.c[4]>>63) | ||||
|                 d.d[4] = d.c[3] ^ (d.c[0]<<1 ^ d.c[0]>>63) | ||||
| 
 | ||||
|                 d.a[0] ^= d.d[0] | ||||
|                 d.a[1] ^= d.d[1] | ||||
|                 d.a[2] ^= d.d[2] | ||||
|                 d.a[3] ^= d.d[3] | ||||
|                 d.a[4] ^= d.d[4] | ||||
|                 d.a[5] ^= d.d[0] | ||||
|                 d.a[6] ^= d.d[1] | ||||
|                 d.a[7] ^= d.d[2] | ||||
|                 d.a[8] ^= d.d[3] | ||||
|                 d.a[9] ^= d.d[4] | ||||
|                 d.a[10] ^= d.d[0] | ||||
|                 d.a[11] ^= d.d[1] | ||||
|                 d.a[12] ^= d.d[2] | ||||
|                 d.a[13] ^= d.d[3] | ||||
|                 d.a[14] ^= d.d[4] | ||||
|                 d.a[15] ^= d.d[0] | ||||
|                 d.a[16] ^= d.d[1] | ||||
|                 d.a[17] ^= d.d[2] | ||||
|                 d.a[18] ^= d.d[3] | ||||
|                 d.a[19] ^= d.d[4] | ||||
|                 d.a[20] ^= d.d[0] | ||||
|                 d.a[21] ^= d.d[1] | ||||
|                 d.a[22] ^= d.d[2] | ||||
|                 d.a[23] ^= d.d[3] | ||||
|                 d.a[24] ^= d.d[4] | ||||
| 
 | ||||
|                 // ρ and π steps
 | ||||
|                 d.b[0] = d.a[0] | ||||
|                 d.b[1] = d.a[6]<<ro_06 ^ d.a[6]>>(64-ro_06) | ||||
|                 d.b[2] = d.a[12]<<ro_12 ^ d.a[12]>>(64-ro_12) | ||||
|                 d.b[3] = d.a[18]<<ro_18 ^ d.a[18]>>(64-ro_18) | ||||
|                 d.b[4] = d.a[24]<<ro_24 ^ d.a[24]>>(64-ro_24) | ||||
|                 d.b[5] = d.a[3]<<ro_15 ^ d.a[3]>>(64-ro_15) | ||||
|                 d.b[6] = d.a[9]<<ro_21 ^ d.a[9]>>(64-ro_21) | ||||
|                 d.b[7] = d.a[10]<<ro_02 ^ d.a[10]>>(64-ro_02) | ||||
|                 d.b[8] = d.a[16]<<ro_08 ^ d.a[16]>>(64-ro_08) | ||||
|                 d.b[9] = d.a[22]<<ro_14 ^ d.a[22]>>(64-ro_14) | ||||
|                 d.b[10] = d.a[1]<<ro_05 ^ d.a[1]>>(64-ro_05) | ||||
|                 d.b[11] = d.a[7]<<ro_11 ^ d.a[7]>>(64-ro_11) | ||||
|                 d.b[12] = d.a[13]<<ro_17 ^ d.a[13]>>(64-ro_17) | ||||
|                 d.b[13] = d.a[19]<<ro_23 ^ d.a[19]>>(64-ro_23) | ||||
|                 d.b[14] = d.a[20]<<ro_04 ^ d.a[20]>>(64-ro_04) | ||||
|                 d.b[15] = d.a[4]<<ro_20 ^ d.a[4]>>(64-ro_20) | ||||
|                 d.b[16] = d.a[5]<<ro_01 ^ d.a[5]>>(64-ro_01) | ||||
|                 d.b[17] = d.a[11]<<ro_07 ^ d.a[11]>>(64-ro_07) | ||||
|                 d.b[18] = d.a[17]<<ro_13 ^ d.a[17]>>(64-ro_13) | ||||
|                 d.b[19] = d.a[23]<<ro_19 ^ d.a[23]>>(64-ro_19) | ||||
|                 d.b[20] = d.a[2]<<ro_10 ^ d.a[2]>>(64-ro_10) | ||||
|                 d.b[21] = d.a[8]<<ro_16 ^ d.a[8]>>(64-ro_16) | ||||
|                 d.b[22] = d.a[14]<<ro_22 ^ d.a[14]>>(64-ro_22) | ||||
|                 d.b[23] = d.a[15]<<ro_03 ^ d.a[15]>>(64-ro_03) | ||||
|                 d.b[24] = d.a[21]<<ro_09 ^ d.a[21]>>(64-ro_09) | ||||
| 
 | ||||
|                 // χ step
 | ||||
|                 d.a[0] = d.b[0] ^ (^d.b[1] & d.b[2]) | ||||
|                 d.a[1] = d.b[1] ^ (^d.b[2] & d.b[3]) | ||||
|                 d.a[2] = d.b[2] ^ (^d.b[3] & d.b[4]) | ||||
|                 d.a[3] = d.b[3] ^ (^d.b[4] & d.b[0]) | ||||
|                 d.a[4] = d.b[4] ^ (^d.b[0] & d.b[1]) | ||||
|                 d.a[5] = d.b[5] ^ (^d.b[6] & d.b[7]) | ||||
|                 d.a[6] = d.b[6] ^ (^d.b[7] & d.b[8]) | ||||
|                 d.a[7] = d.b[7] ^ (^d.b[8] & d.b[9]) | ||||
|                 d.a[8] = d.b[8] ^ (^d.b[9] & d.b[5]) | ||||
|                 d.a[9] = d.b[9] ^ (^d.b[5] & d.b[6]) | ||||
|                 d.a[10] = d.b[10] ^ (^d.b[11] & d.b[12]) | ||||
|                 d.a[11] = d.b[11] ^ (^d.b[12] & d.b[13]) | ||||
|                 d.a[12] = d.b[12] ^ (^d.b[13] & d.b[14]) | ||||
|                 d.a[13] = d.b[13] ^ (^d.b[14] & d.b[10]) | ||||
|                 d.a[14] = d.b[14] ^ (^d.b[10] & d.b[11]) | ||||
|                 d.a[15] = d.b[15] ^ (^d.b[16] & d.b[17]) | ||||
|                 d.a[16] = d.b[16] ^ (^d.b[17] & d.b[18]) | ||||
|                 d.a[17] = d.b[17] ^ (^d.b[18] & d.b[19]) | ||||
|                 d.a[18] = d.b[18] ^ (^d.b[19] & d.b[15]) | ||||
|                 d.a[19] = d.b[19] ^ (^d.b[15] & d.b[16]) | ||||
|                 d.a[20] = d.b[20] ^ (^d.b[21] & d.b[22]) | ||||
|                 d.a[21] = d.b[21] ^ (^d.b[22] & d.b[23]) | ||||
|                 d.a[22] = d.b[22] ^ (^d.b[23] & d.b[24]) | ||||
|                 d.a[23] = d.b[23] ^ (^d.b[24] & d.b[20]) | ||||
|                 d.a[24] = d.b[24] ^ (^d.b[20] & d.b[21]) | ||||
| 
 | ||||
|                 // ι step
 | ||||
|                 d.a[0] ^= roundConstant | ||||
|         } | ||||
| } | ||||
							
								
								
									
										216
									
								
								crypto/sha3/sha3.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								crypto/sha3/sha3.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,216 @@ | ||||
| // Copyright 2013 The Go Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a BSD-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| // Package sha3 implements the SHA3 hash algorithm (formerly called Keccak) chosen by NIST in 2012.
 | ||||
| // This file provides a SHA3 implementation which implements the standard hash.Hash interface.
 | ||||
| // Writing input data, including padding, and reading output data are computed in this file.
 | ||||
| // Note that the current implementation can compute the hash of an integral number of bytes only.
 | ||||
| // This is a consequence of the hash interface in which a buffer of bytes is passed in.
 | ||||
| // The internals of the Keccak-f function are computed in keccakf.go.
 | ||||
| // For the detailed specification, refer to the Keccak web site (http://keccak.noekeon.org/).
 | ||||
| package sha3 | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"hash" | ||||
| ) | ||||
| 
 | ||||
| // laneSize is the size in bytes of each "lane" of the internal state of SHA3 (5 * 5 * 8).
 | ||||
| // Note that changing this size would requires using a type other than uint64 to store each lane.
 | ||||
| const laneSize = 8 | ||||
| 
 | ||||
| // sliceSize represents the dimensions of the internal state, a square matrix of
 | ||||
| // sliceSize ** 2 lanes. This is the size of both the "rows" and "columns" dimensions in the
 | ||||
| // terminology of the SHA3 specification.
 | ||||
| const sliceSize = 5 | ||||
| 
 | ||||
| // numLanes represents the total number of lanes in the state.
 | ||||
| const numLanes = sliceSize * sliceSize | ||||
| 
 | ||||
| // stateSize is the size in bytes of the internal state of SHA3 (5 * 5 * WSize).
 | ||||
| const stateSize = laneSize * numLanes | ||||
| 
 | ||||
| // digest represents the partial evaluation of a checksum.
 | ||||
| // Note that capacity, and not outputSize, is the critical security parameter, as SHA3 can output
 | ||||
| // an arbitrary number of bytes for any given capacity. The Keccak proposal recommends that
 | ||||
| // capacity = 2*outputSize to ensure that finding a collision of size outputSize requires
 | ||||
| // O(2^{outputSize/2}) computations (the birthday lower bound). Future standards may modify the
 | ||||
| // capacity/outputSize ratio to allow for more output with lower cryptographic security.
 | ||||
| type digest struct { | ||||
| 	a          [numLanes]uint64  // main state of the hash
 | ||||
| 	b          [numLanes]uint64  // intermediate states
 | ||||
| 	c          [sliceSize]uint64 // intermediate states
 | ||||
| 	d          [sliceSize]uint64 // intermediate states
 | ||||
| 	outputSize int               // desired output size in bytes
 | ||||
| 	capacity   int               // number of bytes to leave untouched during squeeze/absorb
 | ||||
| 	absorbed   int               // number of bytes absorbed thus far
 | ||||
| } | ||||
| 
 | ||||
| // minInt returns the lesser of two integer arguments, to simplify the absorption routine.
 | ||||
| func minInt(v1, v2 int) int { | ||||
| 	if v1 <= v2 { | ||||
| 		return v1 | ||||
| 	} | ||||
| 	return v2 | ||||
| } | ||||
| 
 | ||||
| // rate returns the number of bytes of the internal state which can be absorbed or squeezed
 | ||||
| // in between calls to the permutation function.
 | ||||
| func (d *digest) rate() int { | ||||
| 	return stateSize - d.capacity | ||||
| } | ||||
| 
 | ||||
| // Reset clears the internal state by zeroing bytes in the state buffer.
 | ||||
| // This can be skipped for a newly-created hash state; the default zero-allocated state is correct.
 | ||||
| func (d *digest) Reset() { | ||||
| 	d.absorbed = 0 | ||||
| 	for i := range d.a { | ||||
| 		d.a[i] = 0 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // BlockSize, required by the hash.Hash interface, does not have a standard intepretation
 | ||||
| // for a sponge-based construction like SHA3. We return the data rate: the number of bytes which
 | ||||
| // can be absorbed per invocation of the permutation function. For Merkle-Damgård based hashes
 | ||||
| // (ie SHA1, SHA2, MD5) the output size of the internal compression function is returned.
 | ||||
| // We consider this to be roughly equivalent because it represents the number of bytes of output
 | ||||
| // produced per cryptographic operation.
 | ||||
| func (d *digest) BlockSize() int { return d.rate() } | ||||
| 
 | ||||
| // Size returns the output size of the hash function in bytes.
 | ||||
| func (d *digest) Size() int { | ||||
| 	return d.outputSize | ||||
| } | ||||
| 
 | ||||
| // unalignedAbsorb is a helper function for Write, which absorbs data that isn't aligned with an
 | ||||
| // 8-byte lane. This requires shifting the individual bytes into position in a uint64.
 | ||||
| func (d *digest) unalignedAbsorb(p []byte) { | ||||
| 	var t uint64 | ||||
| 	for i := len(p) - 1; i >= 0; i-- { | ||||
| 		t <<= 8 | ||||
| 		t |= uint64(p[i]) | ||||
| 	} | ||||
| 	offset := (d.absorbed) % d.rate() | ||||
| 	t <<= 8 * uint(offset%laneSize) | ||||
| 	d.a[offset/laneSize] ^= t | ||||
| 	d.absorbed += len(p) | ||||
| } | ||||
| 
 | ||||
| // Write "absorbs" bytes into the state of the SHA3 hash, updating as needed when the sponge
 | ||||
| // "fills up" with rate() bytes. Since lanes are stored internally as type uint64, this requires
 | ||||
| // converting the incoming bytes into uint64s using a little endian interpretation. This
 | ||||
| // implementation is optimized for large, aligned writes of multiples of 8 bytes (laneSize).
 | ||||
| // Non-aligned or uneven numbers of bytes require shifting and are slower.
 | ||||
| func (d *digest) Write(p []byte) (int, error) { | ||||
| 	// An initial offset is needed if the we aren't absorbing to the first lane initially.
 | ||||
| 	offset := d.absorbed % d.rate() | ||||
| 	toWrite := len(p) | ||||
| 
 | ||||
| 	// The first lane may need to absorb unaligned and/or incomplete data.
 | ||||
| 	if (offset%laneSize != 0 || len(p) < 8) && len(p) > 0 { | ||||
| 		toAbsorb := minInt(laneSize-(offset%laneSize), len(p)) | ||||
| 		d.unalignedAbsorb(p[:toAbsorb]) | ||||
| 		p = p[toAbsorb:] | ||||
| 		offset = (d.absorbed) % d.rate() | ||||
| 
 | ||||
| 		// For every rate() bytes absorbed, the state must be permuted via the F Function.
 | ||||
| 		if (d.absorbed)%d.rate() == 0 { | ||||
| 			d.keccakF() | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// This loop should absorb the bulk of the data into full, aligned lanes.
 | ||||
| 	// It will call the update function as necessary.
 | ||||
| 	for len(p) > 7 { | ||||
| 		firstLane := offset / laneSize | ||||
| 		lastLane := minInt(d.rate()/laneSize, firstLane+len(p)/laneSize) | ||||
| 
 | ||||
| 		// This inner loop absorbs input bytes into the state in groups of 8, converted to uint64s.
 | ||||
| 		for lane := firstLane; lane < lastLane; lane++ { | ||||
| 			d.a[lane] ^= binary.LittleEndian.Uint64(p[:laneSize]) | ||||
| 			p = p[laneSize:] | ||||
| 		} | ||||
| 		d.absorbed += (lastLane - firstLane) * laneSize | ||||
| 		// For every rate() bytes absorbed, the state must be permuted via the F Function.
 | ||||
| 		if (d.absorbed)%d.rate() == 0 { | ||||
| 			d.keccakF() | ||||
| 		} | ||||
| 
 | ||||
| 		offset = 0 | ||||
| 	} | ||||
| 
 | ||||
| 	// If there are insufficient bytes to fill the final lane, an unaligned absorption.
 | ||||
| 	// This should always start at a correct lane boundary though, or else it would be caught
 | ||||
| 	// by the uneven opening lane case above.
 | ||||
| 	if len(p) > 0 { | ||||
| 		d.unalignedAbsorb(p) | ||||
| 	} | ||||
| 
 | ||||
| 	return toWrite, nil | ||||
| } | ||||
| 
 | ||||
| // pad computes the SHA3 padding scheme based on the number of bytes absorbed.
 | ||||
| // The padding is a 1 bit, followed by an arbitrary number of 0s and then a final 1 bit, such that
 | ||||
| // the input bits plus padding bits are a multiple of rate(). Adding the padding simply requires
 | ||||
| // xoring an opening and closing bit into the appropriate lanes.
 | ||||
| func (d *digest) pad() { | ||||
| 	offset := d.absorbed % d.rate() | ||||
| 	// The opening pad bit must be shifted into position based on the number of bytes absorbed
 | ||||
| 	padOpenLane := offset / laneSize | ||||
| 	d.a[padOpenLane] ^= 0x0000000000000001 << uint(8*(offset%laneSize)) | ||||
| 	// The closing padding bit is always in the last position
 | ||||
| 	padCloseLane := (d.rate() / laneSize) - 1 | ||||
| 	d.a[padCloseLane] ^= 0x8000000000000000 | ||||
| } | ||||
| 
 | ||||
| // finalize prepares the hash to output data by padding and one final permutation of the state.
 | ||||
| func (d *digest) finalize() { | ||||
| 	d.pad() | ||||
| 	d.keccakF() | ||||
| } | ||||
| 
 | ||||
| // squeeze outputs an arbitrary number of bytes from the hash state.
 | ||||
| // Squeezing can require multiple calls to the F function (one per rate() bytes squeezed),
 | ||||
| // although this is not the case for standard SHA3 parameters. This implementation only supports
 | ||||
| // squeezing a single time, subsequent squeezes may lose alignment. Future implementations
 | ||||
| // may wish to support multiple squeeze calls, for example to support use as a PRNG.
 | ||||
| func (d *digest) squeeze(in []byte, toSqueeze int) []byte { | ||||
| 	// Because we read in blocks of laneSize, we need enough room to read
 | ||||
| 	// an integral number of lanes
 | ||||
| 	needed := toSqueeze + (laneSize-toSqueeze%laneSize)%laneSize | ||||
| 	if cap(in)-len(in) < needed { | ||||
| 		newIn := make([]byte, len(in), len(in)+needed) | ||||
| 		copy(newIn, in) | ||||
| 		in = newIn | ||||
| 	} | ||||
| 	out := in[len(in) : len(in)+needed] | ||||
| 
 | ||||
| 	for len(out) > 0 { | ||||
| 		for i := 0; i < d.rate() && len(out) > 0; i += laneSize { | ||||
| 			binary.LittleEndian.PutUint64(out[:], d.a[i/laneSize]) | ||||
| 			out = out[laneSize:] | ||||
| 		} | ||||
| 		if len(out) > 0 { | ||||
| 			d.keccakF() | ||||
| 		} | ||||
| 	} | ||||
| 	return in[:len(in)+toSqueeze] // Re-slice in case we wrote extra data.
 | ||||
| } | ||||
| 
 | ||||
| // Sum applies padding to the hash state and then squeezes out the desired nubmer of output bytes.
 | ||||
| func (d *digest) Sum(in []byte) []byte { | ||||
| 	// Make a copy of the original hash so that caller can keep writing and summing.
 | ||||
| 	dup := *d | ||||
| 	dup.finalize() | ||||
| 	return dup.squeeze(in, dup.outputSize) | ||||
| } | ||||
| 
 | ||||
| // The NewKeccakX constructors enable initializing a hash in any of the four recommend sizes
 | ||||
| // from the Keccak specification, all of which set capacity=2*outputSize. Note that the final
 | ||||
| // NIST standard for SHA3 may specify different input/output lengths.
 | ||||
| // The output size is indicated in bits but converted into bytes internally.
 | ||||
| func NewKeccak224() hash.Hash { return &digest{outputSize: 224 / 8, capacity: 2 * 224 / 8} } | ||||
| func NewKeccak256() hash.Hash { return &digest{outputSize: 256 / 8, capacity: 2 * 256 / 8} } | ||||
| func NewKeccak384() hash.Hash { return &digest{outputSize: 384 / 8, capacity: 2 * 384 / 8} } | ||||
| func NewKeccak512() hash.Hash { return &digest{outputSize: 512 / 8, capacity: 2 * 512 / 8} } | ||||
| @ -8,9 +8,9 @@ import ( | ||||
| 	"net" | ||||
| 	"os" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto/secp256k1" | ||||
| 	"github.com/ethereum/go-ethereum/logger" | ||||
| 	"github.com/ethereum/go-ethereum/p2p" | ||||
| 	"github.com/obscuren/secp256k1-go" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
|  | ||||
| @ -6,9 +6,9 @@ import ( | ||||
| 	"math/rand" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto/sha3" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/ethereum/go-ethereum/logger" | ||||
| 	"github.com/obscuren/sha3" | ||||
| ) | ||||
| 
 | ||||
| var powlogger = logger.NewLogger("POW") | ||||
|  | ||||
| @ -6,10 +6,10 @@ import ( | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/crypto/sha3" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/ethereum/go-ethereum/logger" | ||||
| 	"github.com/ethereum/go-ethereum/pow" | ||||
| 	"github.com/obscuren/sha3" | ||||
| ) | ||||
| 
 | ||||
| var powlogger = logger.NewLogger("POW") | ||||
|  | ||||
							
								
								
									
										4
									
								
								tests/files/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								tests/files/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| venv/ | ||||
| *~ | ||||
| *.swp | ||||
| .vagrant/ | ||||
							
								
								
									
										53
									
								
								tests/files/VMTests/RandomTests/201501151106PYTHON.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								tests/files/VMTests/RandomTests/201501151106PYTHON.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| { | ||||
|     "randomVMtest" : { | ||||
|         "callcreates" : [ | ||||
|         ], | ||||
|         "env" : { | ||||
|             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", | ||||
|             "currentDifficulty" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", | ||||
|             "currentGasLimit" : "1000000", | ||||
|             "currentNumber" : "300", | ||||
|             "currentTimestamp" : "2", | ||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" | ||||
|         }, | ||||
|         "exec" : { | ||||
|             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||
|             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "code" : "0x4142414131424043923a58f2", | ||||
|             "data" : "0x", | ||||
|             "gas" : "10000", | ||||
|             "gasPrice" : "100000000000000", | ||||
|             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "value" : "1000000000000000000" | ||||
|         }, | ||||
|         "gas" : "9940", | ||||
|         "logs" : [ | ||||
|         ], | ||||
|         "out" : "0x", | ||||
|         "post" : { | ||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||
|                 "balance" : "1000000000000000000", | ||||
|                 "code" : "0x4142414131424043923a58f2", | ||||
|                 "nonce" : "0", | ||||
|                 "storage" : { | ||||
|                 } | ||||
|             }, | ||||
|             "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { | ||||
|                 "balance" : "0", | ||||
|                 "code" : "0x", | ||||
|                 "nonce" : "0", | ||||
|                 "storage" : { | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pre" : { | ||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||
|                 "balance" : "1000000000000000000", | ||||
|                 "code" : "0x4142414131424043923a58f2", | ||||
|                 "nonce" : "0", | ||||
|                 "storage" : { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								tests/files/VMTests/RandomTests/201501191458PYTHON.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/files/VMTests/RandomTests/201501191458PYTHON.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| { | ||||
|     "randomVMtest" : { | ||||
|         "env" : { | ||||
|             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", | ||||
|             "currentDifficulty" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", | ||||
|             "currentGasLimit" : "1000000", | ||||
|             "currentNumber" : "300", | ||||
|             "currentTimestamp" : "2", | ||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" | ||||
|         }, | ||||
|         "exec" : { | ||||
|             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||
|             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "code" : "0x4243434440448143f2a231f1", | ||||
|             "data" : "0x", | ||||
|             "gas" : "10000", | ||||
|             "gasPrice" : "100000000000000", | ||||
|             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "value" : "1000000000000000000" | ||||
|         }, | ||||
|         "pre" : { | ||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||
|                 "balance" : "1000000000000000000", | ||||
|                 "code" : "0x4243434440448143f2a231f1", | ||||
|                 "nonce" : "0", | ||||
|                 "storage" : { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								tests/files/VMTests/RandomTests/201501191859PYTHON.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/files/VMTests/RandomTests/201501191859PYTHON.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| { | ||||
|     "randomVMtest" : { | ||||
|         "env" : { | ||||
|             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", | ||||
|             "currentDifficulty" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", | ||||
|             "currentGasLimit" : "1000000", | ||||
|             "currentNumber" : "300", | ||||
|             "currentTimestamp" : "2", | ||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" | ||||
|         }, | ||||
|         "exec" : { | ||||
|             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||
|             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "code" : "0x4243434244444340f201186211907055", | ||||
|             "data" : "0x", | ||||
|             "gas" : "10000", | ||||
|             "gasPrice" : "100000000000000", | ||||
|             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "value" : "1000000000000000000" | ||||
|         }, | ||||
|         "pre" : { | ||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||
|                 "balance" : "1000000000000000000", | ||||
|                 "code" : "0x4243434244444340f201186211907055", | ||||
|                 "nonce" : "0", | ||||
|                 "storage" : { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								tests/files/VMTests/RandomTests/201501191953PYTHON.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/files/VMTests/RandomTests/201501191953PYTHON.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| { | ||||
|     "randomVMtest" : { | ||||
|         "env" : { | ||||
|             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", | ||||
|             "currentDifficulty" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", | ||||
|             "currentGasLimit" : "1000000", | ||||
|             "currentNumber" : "300", | ||||
|             "currentTimestamp" : "2", | ||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" | ||||
|         }, | ||||
|         "exec" : { | ||||
|             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||
|             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "code" : "0x434342444041454545045bf2f23a55", | ||||
|             "data" : "0x", | ||||
|             "gas" : "10000", | ||||
|             "gasPrice" : "100000000000000", | ||||
|             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "value" : "1000000000000000000" | ||||
|         }, | ||||
|         "pre" : { | ||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||
|                 "balance" : "1000000000000000000", | ||||
|                 "code" : "0x434342444041454545045bf2f23a55", | ||||
|                 "nonce" : "0", | ||||
|                 "storage" : { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -249,5 +249,63 @@ | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "sha3_bigOffset" : { | ||||
|         "env" : { | ||||
|             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", | ||||
|             "currentDifficulty" : "256", | ||||
|             "currentGasLimit" : "1000000", | ||||
|             "currentNumber" : "0", | ||||
|             "currentTimestamp" : "1", | ||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" | ||||
|         }, | ||||
|         "exec" : { | ||||
|             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||
|             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "code" : "0x60027e0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", | ||||
|             "data" : "0x", | ||||
|             "gas" : "1099511627776", | ||||
|             "gasPrice" : "1", | ||||
|             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "value" : "115792089237316195423570985008687907853269984665640564039457584007913129639935" | ||||
|         }, | ||||
|         "pre" : { | ||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||
|                 "balance" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", | ||||
|                 "code" : "0x60027e0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", | ||||
|                 "nonce" : "0", | ||||
|                 "storage" : { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "sha3_bigSize" : { | ||||
|         "env" : { | ||||
|             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", | ||||
|             "currentDifficulty" : "256", | ||||
|             "currentGasLimit" : "1000000", | ||||
|             "currentNumber" : "0", | ||||
|             "currentTimestamp" : "1", | ||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" | ||||
|         }, | ||||
|         "exec" : { | ||||
|             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||
|             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "code" : "0x7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", | ||||
|             "data" : "0x", | ||||
|             "gas" : "1099511627776", | ||||
|             "gasPrice" : "1", | ||||
|             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||
|             "value" : "115792089237316195423570985008687907853269984665640564039457584007913129639935" | ||||
|         }, | ||||
|         "pre" : { | ||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||
|                 "balance" : "115792089237316195423570985008687907853269984665640564039457584007913129639935", | ||||
|                 "code" : "0x7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20600055", | ||||
|                 "nonce" : "0", | ||||
|                 "storage" : { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										5
									
								
								tests/files/ansible/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/files/ansible/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| # Automatic deployment of the random test generator | ||||
| 
 | ||||
| Testing is done in a Vagrant virtual machine | ||||
| 
 | ||||
| install vagrant, virtualbox, ansible, then do `vagrant up`. It should provison a basic machine. `vagrant ssh` to verify the machine is working as expected. `vagrant terminate` to reset machine to clean state. | ||||
							
								
								
									
										78
									
								
								tests/files/ansible/Vagrantfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								tests/files/ansible/Vagrantfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| # -*- mode: ruby -*- | ||||
| # vi: set ft=ruby : | ||||
| 
 | ||||
| # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! | ||||
| VAGRANTFILE_API_VERSION ||= "2" | ||||
| 
 | ||||
| Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| | ||||
|   # All Vagrant configuration is done here. The most common configuration | ||||
|   # options are documented and commented below. For a complete reference, | ||||
|   # please see the online documentation at vagrantup.com. | ||||
| 
 | ||||
|   # Every Vagrant virtual environment requires a box to build off of. | ||||
|   config.vm.box = "ubuntu/trusty64" | ||||
|   config.vm.define "random-test" | ||||
| 
 | ||||
|   # Disable automatic box update checking. If you disable this, then | ||||
|   # boxes will only be checked for updates when the user runs | ||||
|   # `vagrant box outdated`. This is not recommended. | ||||
|   # config.vm.box_check_update = false | ||||
| 
 | ||||
|   # Create a forwarded port mapping which allows access to a specific port | ||||
|   # within the machine from a port on the host machine. In the example below, | ||||
|   # accessing "localhost:8080" will access port 80 on the guest machine. | ||||
|   # config.vm.network "forwarded_port", guest: 80, host: 8080 | ||||
| 
 | ||||
|   # Create a private network, which allows host-only access to the machine | ||||
|   # using a specific IP. | ||||
|   # config.vm.network "private_network", ip: "192.168.33.10" | ||||
| 
 | ||||
|   # Create a public network, which generally matched to bridged network. | ||||
|   # Bridged networks make the machine appear as another physical device on | ||||
|   # your network. | ||||
|   # config.vm.network "public_network" | ||||
| 
 | ||||
|   # If true, then any SSH connections made will enable agent forwarding. | ||||
|   # Default value: false | ||||
|   # config.ssh.forward_agent = true | ||||
| 
 | ||||
|   # Share an additional folder to the guest VM. The first argument is | ||||
|   # the path on the host to the actual folder. The second argument is | ||||
|   # the path on the guest to mount the folder. And the optional third | ||||
|   # argument is a set of non-required options. | ||||
|   # config.vm.synced_folder "../data", "/vagrant_data" | ||||
| 
 | ||||
|   # Provider-specific configuration so you can fine-tune various | ||||
|   # backing providers for Vagrant. These expose provider-specific options. | ||||
|   # Example for VirtualBox: | ||||
|   # | ||||
|   # config.vm.provider "virtualbox" do |vb| | ||||
|   #   # Don't boot with headless mode | ||||
|   #   vb.gui = true | ||||
|   # | ||||
|   #   # Use VBoxManage to customize the VM. For example to change memory: | ||||
|   #   vb.customize ["modifyvm", :id, "--memory", "1024"] | ||||
|   # end | ||||
|    | ||||
| 
 | ||||
|   config.vm.provider "virtualbox" do |vb|  | ||||
|   		# Ubuntu / Virtualbox workaround.  | ||||
|   		# see http://askubuntu.com/questions/238040/how-do-i-fix-name-service-for-vagrant-client | ||||
| 	    vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] | ||||
| 
 | ||||
| 		# cpp client needs a lot of RAM to build | ||||
|         vb.customize ["modifyvm", :id, "--memory", "2048"] | ||||
|   end | ||||
|    | ||||
|   # | ||||
|   # View the documentation for the provider you're using for more | ||||
|   # information on available options. | ||||
|   | ||||
|    | ||||
|   # Ansible | ||||
|   config.vm.provision "ansible" do |ansible| | ||||
|     	ansible.playbook = "site.yml" | ||||
|   end | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
							
								
								
									
										8
									
								
								tests/files/ansible/host-config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tests/files/ansible/host-config.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| --- | ||||
| - name: Provision the operation system for tests | ||||
|   # testing | ||||
|   hosts: all | ||||
|   # live | ||||
|   # hosts: TDB  | ||||
|   roles: | ||||
|       - common | ||||
							
								
								
									
										28
									
								
								tests/files/ansible/roles/common/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								tests/files/ansible/roles/common/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| --- | ||||
| - name: install docker | ||||
|   sudo: true | ||||
|   # install script from https://docs.docker.com/installation/ubuntulinux/ | ||||
|   shell: curl -sSL https://get.docker.com/ubuntu/ | sudo sh   | ||||
| 
 | ||||
| - name: install package dependencies | ||||
|   sudo: true | ||||
|   apt: name={{ item }} | ||||
|   with_items: | ||||
|       - python-pip | ||||
|       - htop | ||||
| 
 | ||||
| - name: install python dependencies | ||||
|   sudo: true | ||||
|   pip: name=docker-py | ||||
| 
 | ||||
| 
 | ||||
| - name: enable docker for standard user | ||||
|   sudo: true | ||||
|   # todo: how to logout after this command, otherwise won't be effective in this play | ||||
|   user: name=vagrant groups=docker append=yes | ||||
| 
 | ||||
| - name: checkout test repo | ||||
|   git: | ||||
|       repo: https://github.com/sveneh/tests.git  | ||||
|       version: develop | ||||
|       dest: git | ||||
							
								
								
									
										18
									
								
								tests/files/ansible/roles/testrunner/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tests/files/ansible/roles/testrunner/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| --- | ||||
| - name: update C++ client | ||||
|   sudo: true   | ||||
|   docker_image: | ||||
|       path: git/ansible/test-files/docker-cpp | ||||
|       name: cpp | ||||
|       state: build | ||||
| 
 | ||||
| - name: update Go client | ||||
|   sudo: true  | ||||
|   docker_image: | ||||
|       path: git/ansible/test-files/docker-go | ||||
|       name: go | ||||
|       state: build | ||||
| 
 | ||||
| - name: Run infinite tests (press ^C to stop) | ||||
|   sudo: true | ||||
|   shell: git/ansible/test-files/testrunner.sh | ||||
							
								
								
									
										3
									
								
								tests/files/ansible/site.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tests/files/ansible/site.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| --- | ||||
| - include: host-config.yml | ||||
| - include: testrunner-config.yml | ||||
							
								
								
									
										32
									
								
								tests/files/ansible/test-files/docker-cpp/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								tests/files/ansible/test-files/docker-cpp/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| # adjusted from https://github.com/ethereum/cpp-ethereum/blob/develop/docker/Dockerfile | ||||
| FROM ubuntu:14.04 | ||||
| 
 | ||||
| ENV DEBIAN_FRONTEND noninteractive | ||||
| RUN apt-get update | ||||
| RUN apt-get upgrade -y | ||||
| 
 | ||||
| # Ethereum dependencies | ||||
| RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget | ||||
| RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons | ||||
| RUN apt-get install -qy libjsoncpp-dev libargtable2-dev | ||||
| 
 | ||||
| # NCurses based GUI (not optional though for a succesful compilation, see https://github.com/ethereum/cpp-ethereum/issues/452 ) | ||||
| RUN apt-get install -qy libncurses5-dev | ||||
| 
 | ||||
| # Qt-based GUI | ||||
| # RUN apt-get install -qy qtbase5-dev qt5-default qtdeclarative5-dev libqt5webkit5-dev | ||||
| 
 | ||||
| # Ethereum PPA | ||||
| RUN apt-get install -qy software-properties-common | ||||
| RUN add-apt-repository ppa:ethereum/ethereum | ||||
| RUN apt-get update | ||||
| RUN apt-get install -qy libcryptopp-dev libjson-rpc-cpp-dev | ||||
| 
 | ||||
| # Build Ethereum (HEADLESS) | ||||
| RUN git clone --depth=1 --branch develop https://github.com/ethereum/cpp-ethereum | ||||
| RUN mkdir -p cpp-ethereum/build | ||||
| RUN cd cpp-ethereum/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DHEADLESS=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install | ||||
| RUN ldconfig | ||||
| 
 | ||||
| ENTRYPOINT ["/cpp-ethereum/build/test/createRandomTest"] | ||||
| 
 | ||||
							
								
								
									
										46
									
								
								tests/files/ansible/test-files/docker-go/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								tests/files/ansible/test-files/docker-go/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| # Adjusted from https://github.com/ethereum/go-ethereum/blob/develop/Dockerfile | ||||
| FROM ubuntu:14.04 | ||||
| 
 | ||||
| ## Environment setup | ||||
| ENV HOME /root | ||||
| ENV GOPATH /root/go | ||||
| ENV PATH /go/bin:/root/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games | ||||
| 
 | ||||
| RUN mkdir -p /root/go | ||||
| ENV DEBIAN_FRONTEND noninteractive | ||||
| 
 | ||||
| ## Install base dependencies | ||||
| RUN apt-get update && apt-get upgrade -y | ||||
| RUN apt-get install -y git mercurial build-essential software-properties-common pkg-config libgmp3-dev libreadline6-dev libpcre3-dev libpcre++-dev | ||||
| 
 | ||||
| ## Build and install Go | ||||
| RUN hg clone -u release https://code.google.com/p/go | ||||
| RUN cd go && hg update go1.4 | ||||
| RUN cd go/src && ./make.bash && go version | ||||
| 
 | ||||
| ## Install GUI dependencies | ||||
| RUN add-apt-repository ppa:ubuntu-sdk-team/ppa -y | ||||
| RUN apt-get update -y | ||||
| RUN apt-get install -y qtbase5-private-dev qtdeclarative5-private-dev libqt5opengl5-dev | ||||
| 
 | ||||
| ## Fetch and install serpent-go | ||||
| RUN go get -v -d github.com/ethereum/serpent-go | ||||
| WORKDIR $GOPATH/src/github.com/ethereum/serpent-go | ||||
| # RUN git checkout master | ||||
| RUN git submodule update --init | ||||
| RUN go install -v | ||||
| 
 | ||||
| # Fetch and install go-ethereum | ||||
| RUN go get -v -d github.com/ethereum/go-ethereum/... | ||||
| WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum | ||||
| 
 | ||||
| RUN git checkout develop | ||||
| 
 | ||||
| RUN git pull | ||||
| RUN ETH_DEPS=$(go list -f '{{.Imports}} {{.TestImports}} {{.XTestImports}}' github.com/ethereum/go-ethereum/... | sed -e 's/\[//g' | sed -e 's/\]//g' | sed -e 's/C //g'); if [ "$ETH_DEPS" ]; then go get $ETH_DEPS; fi | ||||
| RUN go install -v ./cmd/ethtest | ||||
| 
 | ||||
| # Run JSON RPC | ||||
| ENTRYPOINT ["ethtest"] | ||||
| EXPOSE 8080 | ||||
| 
 | ||||
							
								
								
									
										56
									
								
								tests/files/ansible/test-files/testrunner.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										56
									
								
								tests/files/ansible/test-files/testrunner.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,56 @@ | ||||
| #!/bin/bash | ||||
| 
 | ||||
| # create random virtual machine test | ||||
| #cd ~/software/Ethereum/pyethereum (python has local dependencies so only works from within the directory) | ||||
| while [ 1 ] | ||||
| do	 | ||||
| 	TEST="$(docker run --rm cpp)" | ||||
| 	# echo "$TEST" | ||||
| 
 | ||||
| 	# test pyethereum | ||||
| 	 | ||||
| 	 #OUTPUT_PYTHON="$(python ./tests/test_vm.py "$TEST")" | ||||
| 	 #RESULT_PYTHON=$? | ||||
| 
 | ||||
| 	# test go | ||||
| 	 OUTPUT_GO="$(docker run --rm go "$TEST")" | ||||
| 	 RESULT_GO=$? | ||||
| 
 | ||||
| 	# test cpp-jit | ||||
| 	#OUTPUT_CPPJIT="$(~/software/Ethereum/cpp-ethereum/build/test/checkRandomTest "$TEST")" | ||||
| 	#RESULT_CPPJIT=$? | ||||
| 
 | ||||
| # go fails | ||||
| if [ "$RESULT_GO" -ne 0 ]; then | ||||
| 	echo Failed: | ||||
| 	echo Output_GO: | ||||
| 	echo $OUTPUT_GO | ||||
| 	echo Test: | ||||
| 	echo "$TEST" | ||||
| 	echo "$TEST" > FailedTest.json | ||||
| 	mv FailedTest.json $(date -d "today" +"%Y%m%d%H%M")GO.json # replace with scp to central server | ||||
| fi | ||||
| 
 | ||||
| # python fails | ||||
| #if [ "$RESULT_PYTHON" -ne 0 ]; then | ||||
| #	echo Failed: | ||||
| #	echo Output_PYTHON: | ||||
| #	echo $OUTPUT_PYTHON | ||||
| #	echo Test: | ||||
| #	echo "$TEST" | ||||
| #	echo "$TEST" > FailedTest.json | ||||
| #	mv FailedTest.json $(date -d "today" +"%Y%m%d%H%M")PYTHON.json | ||||
| #fi | ||||
| 
 | ||||
| # cppjit fails | ||||
| #if [ "$RESULT_CPPJIT" -ne 0 ]; then | ||||
| #	echo Failed: | ||||
| #	echo Output_CPPJIT: | ||||
| #	echo $OUTPUT_CPPJIT | ||||
| #	echo Test: | ||||
| #	echo "$TEST" | ||||
| #	echo "$TEST" > FailedTest.json | ||||
| #	mv FailedTest.json $(date -d "today" +"%Y%m%d%H%M")CPPJIT.json | ||||
| #fi | ||||
| done | ||||
| 
 | ||||
							
								
								
									
										12
									
								
								tests/files/ansible/testrunner-config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/files/ansible/testrunner-config.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| --- | ||||
| - name: preparing and running tests | ||||
|   # testing | ||||
|   hosts: all | ||||
|   # live | ||||
|   # hosts: TBD | ||||
|    | ||||
|   # TODO use the right user for configuring, until credentials set, stay with default vagrant user  | ||||
|   # remote_user: ubuntu | ||||
|    | ||||
|   roles: | ||||
|       - testrunner | ||||
| @ -1,36 +1,6 @@ | ||||
| module.exports = { | ||||
|   blockgenesis: require('./BasicTests/blockgenesistest'), | ||||
|   genesishashes: require('./BasicTests/genesishashestest'), | ||||
|   hexencode: require('./BasicTests/hexencodetest'), | ||||
|   keyaddrtests: require('./BasicTests/keyaddrtest'), | ||||
|   rlptest: require('./BasicTests/rlptest'), | ||||
|   trieTests: { | ||||
|     trietest: require('./TrieTests/trietest'), | ||||
|     trietestnextprev: require('./TrieTests/trietestnextprev'), | ||||
|     trieanyorder: require('./TrieTests/trieanyorder') | ||||
|   }, | ||||
|   txtest: require('./BasicTests/txtest'), | ||||
|   StateTests: { | ||||
|     stExample: require('./StateTests/stExample.json'), | ||||
|     stInitCodeTest: require('./StateTests/stInitCodeTest.json'), | ||||
|     stLogTests: require('./StateTests/stLogTests.json'), | ||||
|     stPreCompiledContracts: require('./StateTests/stPreCompiledContracts'), | ||||
|     stRecursiveCreate: require('./StateTests/stRecursiveCreate'), | ||||
|     stRefundTest: require('./StateTests/stRefundTest'), | ||||
|     stSpecial: require('./StateTests/stSpecialTest'), | ||||
|     stSystemOperationsTest: require('./StateTests/stSystemOperationsTest'), | ||||
|     stTransactionTest: require('./StateTests/stTransactionTest') | ||||
|   }, | ||||
|   VMTests: { | ||||
|     vmRandom: require('./VMTests/RandomTests/randomTest'), | ||||
|     vmArithmeticTest: require('./VMTests/vmArithmeticTest'), | ||||
|     vmBitwiseLogicOperationTest: require('./VMTests/vmBitwiseLogicOperationTest'), | ||||
|     vmBlockInfoTest: require('./VMTests/vmBlockInfoTest'), | ||||
|     vmEnvironmentalInfoTest: require('./VMTests/vmEnvironmentalInfoTest'), | ||||
|     vmIOandFlowOperationsTest: require('./VMTests/vmIOandFlowOperationsTest'), | ||||
|     vmLogTest: require('./VMTests/vmLogTest'), | ||||
|     vmPushDupSwapTest: require('./VMTests/vmPushDupSwapTest'), | ||||
|     vmSha3Test: require('./VMTests/vmSha3Test'), | ||||
|     vmtests: require('./VMTests/vmtests') | ||||
|   } | ||||
|   basicTests: require('require-all')(__dirname + '/BasicTests/'), | ||||
|   trieTests: require('require-all')(__dirname + '/TrieTests/'), | ||||
|   stateTests: require('require-all')(__dirname + '/StateTests/'), | ||||
|   vmTests: require('require-all')(__dirname + '/VMTests') | ||||
| }; | ||||
|  | ||||
| @ -19,5 +19,8 @@ | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/ethereum/tests/issues" | ||||
|   }, | ||||
|   "homepage": "https://github.com/ethereum/tests" | ||||
|   "homepage": "https://github.com/ethereum/tests", | ||||
|   "dependencies": { | ||||
|     "require-all": "^1.0.0" | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -7,10 +7,10 @@ import ( | ||||
| 	"log" | ||||
| 	"os" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/crypto/secp256k1" | ||||
| 	"github.com/ethereum/go-ethereum/logger" | ||||
| 	"github.com/ethereum/go-ethereum/p2p" | ||||
| 	"github.com/ethereum/go-ethereum/whisper" | ||||
| 	"github.com/obscuren/secp256k1-go" | ||||
| ) | ||||
| 
 | ||||
| func main() { | ||||
|  | ||||
| @ -81,7 +81,7 @@ func (self *peer) broadcast(envelopes []*Envelope) error { | ||||
| 		if err := self.ws.WriteMsg(msg); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		self.peer.Infoln("broadcasted", i, "message(s)") | ||||
| 		self.peer.DebugDetailln("broadcasted", i, "message(s)") | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user