VOTING POWER100.00%
DOWNVOTE POWER100.00%
RESOURCE CREDITS100.00%
REPUTATION PROGRESS0.00%
Net Worth
0.037USD
STEEM
0.001STEEM
SBD
0.001SBD
Effective Power
5.009SP
├── Own SP
0.636SP
└── Incoming DelegationsDeleg
+4.373SP
Detailed Balance
| STEEM | ||
| balance | 0.001STEEM | STEEM |
| market_balance | 0.000STEEM | STEEM |
| savings_balance | 0.000STEEM | STEEM |
| reward_steem_balance | 0.000STEEM | STEEM |
| STEEM POWER | ||
| Own SP | 0.636SP | SP |
| Delegated Out | 0.000SP | SP |
| Delegation In | 4.373SP | SP |
| Effective Power | 5.009SP | SP |
| Reward SP (pending) | 0.000SP | SP |
| SBD | ||
| sbd_balance | 0.001SBD | SBD |
| sbd_conversions | 0.000SBD | SBD |
| sbd_market_balance | 0.000SBD | SBD |
| savings_sbd_balance | 0.000SBD | SBD |
| reward_sbd_balance | 0.000SBD | SBD |
{
"balance": "0.001 STEEM",
"savings_balance": "0.000 STEEM",
"reward_steem_balance": "0.000 STEEM",
"vesting_shares": "1033.711102 VESTS",
"delegated_vesting_shares": "0.000000 VESTS",
"received_vesting_shares": "7109.948704 VESTS",
"sbd_balance": "0.001 SBD",
"savings_sbd_balance": "0.000 SBD",
"reward_sbd_balance": "0.000 SBD",
"conversions": []
}Account Info
| name | icostan |
| id | 258317 |
| rank | 974,718 |
| reputation | 41140234 |
| created | 2017-07-13T20:36:27 |
| recovery_account | steem |
| proxy | None |
| post_count | 9 |
| comment_count | 0 |
| lifetime_vote_count | 0 |
| witnesses_voted_for | 4 |
| last_post | 2019-10-02T07:20:06 |
| last_root_post | 2019-10-02T07:20:06 |
| last_vote_time | 2017-08-12T14:08:39 |
| proxied_vsf_votes | 0, 0, 0, 0 |
| can_vote | 1 |
| voting_power | 0 |
| delayed_votes | 0 |
| balance | 0.001 STEEM |
| savings_balance | 0.000 STEEM |
| sbd_balance | 0.001 SBD |
| savings_sbd_balance | 0.000 SBD |
| vesting_shares | 1033.711102 VESTS |
| delegated_vesting_shares | 0.000000 VESTS |
| received_vesting_shares | 7109.948704 VESTS |
| reward_vesting_balance | 0.000000 VESTS |
| vesting_balance | 0.000 STEEM |
| vesting_withdraw_rate | 0.000000 VESTS |
| next_vesting_withdrawal | 1969-12-31T23:59:59 |
| withdrawn | 0 |
| to_withdraw | 0 |
| withdraw_routes | 0 |
| savings_withdraw_requests | 0 |
| last_account_recovery | 1970-01-01T00:00:00 |
| reset_account | null |
| last_owner_update | 1970-01-01T00:00:00 |
| last_account_update | 2020-04-02T04:27:33 |
| mined | No |
| sbd_seconds | 0 |
| sbd_last_interest_payment | 1970-01-01T00:00:00 |
| savings_sbd_last_interest_payment | 1970-01-01T00:00:00 |
{
"id": 258317,
"name": "icostan",
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM8khvozYSgQesA4HfUsz977WkPUnBJbUxoboqqkSdSURZcgowCq",
1
]
]
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM7wXRVfSTGD8tos5uC444bf8FxeaZuXCmJjjSapRhEKBh2TbsQ3",
1
]
]
},
"posting": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM6x1BPWfk5eFQg3cio62PoSkRYQCCzH99Eo3vXf68xVJSJ15zWB",
1
]
]
},
"memo_key": "STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa",
"json_metadata": "{\"profile\":{\"name\":\"Iulian Costan\",\"about\":\"Computer geek, derivatives trader, crypto hodler.\",\"website\":\"http://iuliancostan.com\",\"location\":\"Romania\"}}",
"posting_json_metadata": "{\"profile\":{\"name\":\"Iulian Costan\",\"about\":\"Software developer, derivatives trader, crypto hodler.\",\"website\":\"http://iuliancostan.com\",\"location\":\"Romania\",\"cover_image\":\"https://cdn.steemitimages.com/DQmRDebpsdxEV3eCyhwTw3yzSRVTmqU9nNP4WaxShFX3dmR/avatar-india.jpg\",\"version\":2}}",
"proxy": "",
"last_owner_update": "1970-01-01T00:00:00",
"last_account_update": "2020-04-02T04:27:33",
"created": "2017-07-13T20:36:27",
"mined": false,
"recovery_account": "steem",
"last_account_recovery": "1970-01-01T00:00:00",
"reset_account": "null",
"comment_count": 0,
"lifetime_vote_count": 0,
"post_count": 9,
"can_vote": true,
"voting_manabar": {
"current_mana": "8143659806",
"last_update_time": 1779067239
},
"downvote_manabar": {
"current_mana": 2035914951,
"last_update_time": 1779067239
},
"voting_power": 0,
"balance": "0.001 STEEM",
"savings_balance": "0.000 STEEM",
"sbd_balance": "0.001 SBD",
"sbd_seconds": "0",
"sbd_seconds_last_update": "2018-12-11T09:26:51",
"sbd_last_interest_payment": "1970-01-01T00:00:00",
"savings_sbd_balance": "0.000 SBD",
"savings_sbd_seconds": "0",
"savings_sbd_seconds_last_update": "1970-01-01T00:00:00",
"savings_sbd_last_interest_payment": "1970-01-01T00:00:00",
"savings_withdraw_requests": 0,
"reward_sbd_balance": "0.000 SBD",
"reward_steem_balance": "0.000 STEEM",
"reward_vesting_balance": "0.000000 VESTS",
"reward_vesting_steem": "0.000 STEEM",
"vesting_shares": "1033.711102 VESTS",
"delegated_vesting_shares": "0.000000 VESTS",
"received_vesting_shares": "7109.948704 VESTS",
"vesting_withdraw_rate": "0.000000 VESTS",
"next_vesting_withdrawal": "1969-12-31T23:59:59",
"withdrawn": 0,
"to_withdraw": 0,
"withdraw_routes": 0,
"curation_rewards": 0,
"posting_rewards": 0,
"proxied_vsf_votes": [
0,
0,
0,
0
],
"witnesses_voted_for": 4,
"last_post": "2019-10-02T07:20:06",
"last_root_post": "2019-10-02T07:20:06",
"last_vote_time": "2017-08-12T14:08:39",
"post_bandwidth": 0,
"pending_claimed_accounts": 0,
"vesting_balance": "0.000 STEEM",
"reputation": 41140234,
"transfer_history": [],
"market_history": [],
"post_history": [],
"vote_history": [],
"other_history": [],
"witness_votes": [
"furion",
"good-karma",
"jerrybanfield",
"steemitboard"
],
"tags_usage": [],
"guest_bloggers": [],
"rank": 974718
}Withdraw Routes
| Incoming | Outgoing |
|---|---|
Empty | Empty |
{
"incoming": [],
"outgoing": []
}From Date
To Date
2026/05/18 01:20:39
2026/05/18 01:20:39
| delegatee | icostan |
| delegator | steem |
| vesting shares | 7109.948704 VESTS |
| Transaction Info | Block #106144750/Trx fbd01f9c3a782816d79e44041d682a0d443404f5 |
View Raw JSON Data
{
"block": 106144750,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "7109.948704 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2026-05-18T01:20:39",
"trx_id": "fbd01f9c3a782816d79e44041d682a0d443404f5",
"trx_in_block": 0,
"virtual_op": 0
}2026/05/12 08:15:57
2026/05/12 08:15:57
| delegatee | icostan |
| delegator | steem |
| vesting shares | 4397.738299 VESTS |
| Transaction Info | Block #105981009/Trx 9e7c0409594b840285e5f30a0ba4438fcbf982b9 |
View Raw JSON Data
{
"block": 105981009,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "4397.738299 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2026-05-12T08:15:57",
"trx_id": "9e7c0409594b840285e5f30a0ba4438fcbf982b9",
"trx_in_block": 1,
"virtual_op": 0
}2026/04/26 00:39:42
2026/04/26 00:39:42
| delegatee | icostan |
| delegator | steem |
| vesting shares | 7122.464460 VESTS |
| Transaction Info | Block #105512370/Trx 89413f0c2bc15922383a616f58d9a5faff6746f0 |
View Raw JSON Data
{
"block": 105512370,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "7122.464460 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2026-04-26T00:39:42",
"trx_id": "89413f0c2bc15922383a616f58d9a5faff6746f0",
"trx_in_block": 0,
"virtual_op": 0
}2026/01/23 10:44:00
2026/01/23 10:44:00
| delegatee | icostan |
| delegator | steem |
| vesting shares | 4439.285118 VESTS |
| Transaction Info | Block #102855325/Trx f4b258f40a488a80a4e4f46ccf7a9534a380120d |
View Raw JSON Data
{
"block": 102855325,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "4439.285118 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2026-01-23T10:44:00",
"trx_id": "f4b258f40a488a80a4e4f46ccf7a9534a380120d",
"trx_in_block": 1,
"virtual_op": 0
}2024/12/17 06:01:15
2024/12/17 06:01:15
| delegatee | icostan |
| delegator | steem |
| vesting shares | 4603.504315 VESTS |
| Transaction Info | Block #91301685/Trx ae565da12b2fa6d901ccfe06a74e36009d3fce59 |
View Raw JSON Data
{
"block": 91301685,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "4603.504315 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2024-12-17T06:01:15",
"trx_id": "ae565da12b2fa6d901ccfe06a74e36009d3fce59",
"trx_in_block": 0,
"virtual_op": 0
}2023/11/13 21:43:33
2023/11/13 21:43:33
| delegatee | icostan |
| delegator | steem |
| vesting shares | 4772.637847 VESTS |
| Transaction Info | Block #79855876/Trx 8bb209fe2f0b2c624abc086fe963dbb2f6fba58a |
View Raw JSON Data
{
"block": 79855876,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "4772.637847 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2023-11-13T21:43:33",
"trx_id": "8bb209fe2f0b2c624abc086fe963dbb2f6fba58a",
"trx_in_block": 0,
"virtual_op": 0
}2023/09/21 23:07:03
2023/09/21 23:07:03
| delegatee | icostan |
| delegator | steem |
| vesting shares | 7709.916633 VESTS |
| Transaction Info | Block #78349370/Trx eb985618efabd58611f6fdf729057427290f516b |
View Raw JSON Data
{
"block": 78349370,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "7709.916633 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2023-09-21T23:07:03",
"trx_id": "eb985618efabd58611f6fdf729057427290f516b",
"trx_in_block": 11,
"virtual_op": 0
}2022/11/03 12:44:33
2022/11/03 12:44:33
| delegatee | icostan |
| delegator | steem |
| vesting shares | 7931.598071 VESTS |
| Transaction Info | Block #69114502/Trx ec8f6ab9b77beb28c67df632f1ffddd435724867 |
View Raw JSON Data
{
"block": 69114502,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "7931.598071 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2022-11-03T12:44:33",
"trx_id": "ec8f6ab9b77beb28c67df632f1ffddd435724867",
"trx_in_block": 4,
"virtual_op": 0
}2022/01/17 11:55:18
2022/01/17 11:55:18
| delegatee | icostan |
| delegator | steem |
| vesting shares | 8152.131302 VESTS |
| Transaction Info | Block #60810567/Trx d0573691e6718110f86c9d9f8d56fde5c325526b |
View Raw JSON Data
{
"block": 60810567,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "8152.131302 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2022-01-17T11:55:18",
"trx_id": "d0573691e6718110f86c9d9f8d56fde5c325526b",
"trx_in_block": 1,
"virtual_op": 0
}2021/06/14 01:47:54
2021/06/14 01:47:54
| delegatee | icostan |
| delegator | steem |
| vesting shares | 8335.899960 VESTS |
| Transaction Info | Block #54608898/Trx c7ae47ae36f06d6ed4f130fbe2f1fc9e8a6c6a70 |
View Raw JSON Data
{
"block": 54608898,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "8335.899960 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2021-06-14T01:47:54",
"trx_id": "c7ae47ae36f06d6ed4f130fbe2f1fc9e8a6c6a70",
"trx_in_block": 1,
"virtual_op": 0
}2020/12/11 12:05:15
2020/12/11 12:05:15
| delegatee | icostan |
| delegator | steem |
| vesting shares | 8523.321934 VESTS |
| Transaction Info | Block #49356311/Trx 8bcde9c434e60b237df4e1d1c4fa130cc840f192 |
View Raw JSON Data
{
"block": 49356311,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "8523.321934 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2020-12-11T12:05:15",
"trx_id": "8bcde9c434e60b237df4e1d1c4fa130cc840f192",
"trx_in_block": 4,
"virtual_op": 0
}2020/12/06 05:42:15
2020/12/06 05:42:15
| delegatee | icostan |
| delegator | steem |
| vesting shares | 1912.543513 VESTS |
| Transaction Info | Block #49207872/Trx 42ad2630d4e16e6e70e845b172e73ad447688bb0 |
View Raw JSON Data
{
"block": 49207872,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "1912.543513 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2020-12-06T05:42:15",
"trx_id": "42ad2630d4e16e6e70e845b172e73ad447688bb0",
"trx_in_block": 2,
"virtual_op": 0
}2020/12/05 15:43:06
2020/12/05 15:43:06
| delegatee | icostan |
| delegator | steem |
| vesting shares | 8529.529788 VESTS |
| Transaction Info | Block #49191405/Trx 81d514310a7e6c084ba44b8235fc62905ec2a095 |
View Raw JSON Data
{
"block": 49191405,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "8529.529788 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2020-12-05T15:43:06",
"trx_id": "81d514310a7e6c084ba44b8235fc62905ec2a095",
"trx_in_block": 1,
"virtual_op": 0
}2020/11/02 17:40:30
2020/11/02 17:40:30
| delegatee | icostan |
| delegator | steem |
| vesting shares | 1920.017158 VESTS |
| Transaction Info | Block #48260200/Trx c6312a02cdb05f355084d57948335d02e92ad7a3 |
View Raw JSON Data
{
"block": 48260200,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "1920.017158 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2020-11-02T17:40:30",
"trx_id": "c6312a02cdb05f355084d57948335d02e92ad7a3",
"trx_in_block": 4,
"virtual_op": 0
}2020/05/09 06:40:30
2020/05/09 06:40:30
| delegatee | icostan |
| delegator | steem |
| vesting shares | 8732.335147 VESTS |
| Transaction Info | Block #43218134/Trx c1ad3dca06e95d47057e6475d12f149f389e58b0 |
View Raw JSON Data
{
"block": 43218134,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "8732.335147 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2020-05-09T06:40:30",
"trx_id": "c1ad3dca06e95d47057e6475d12f149f389e58b0",
"trx_in_block": 7,
"virtual_op": 0
}2020/05/08 10:25:24
2020/05/08 10:25:24
| delegatee | icostan |
| delegator | steem |
| vesting shares | 1953.311140 VESTS |
| Transaction Info | Block #43194400/Trx ac20e33fbf7c894daa9e2ada7fa737eb16ef8ff4 |
View Raw JSON Data
{
"block": 43194400,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "1953.311140 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2020-05-08T10:25:24",
"trx_id": "ac20e33fbf7c894daa9e2ada7fa737eb16ef8ff4",
"trx_in_block": 10,
"virtual_op": 0
}icostanupdated their account properties2020/04/02 04:27:33
icostanupdated their account properties
2020/04/02 04:27:33
| account | icostan |
| extensions | [] |
| json metadata | |
| posting json metadata | {"profile":{"name":"Iulian Costan","about":"Software developer, derivatives trader, crypto hodler.","website":"http://iuliancostan.com","location":"Romania","cover_image":"https://cdn.steemitimages.com/DQmRDebpsdxEV3eCyhwTw3yzSRVTmqU9nNP4WaxShFX3dmR/avatar-india.jpg","version":2}} |
| Transaction Info | Block #42176514/Trx d9520a989fb3a727cc23f6e4687d95746152e96f |
View Raw JSON Data
{
"block": 42176514,
"op": [
"account_update2",
{
"account": "icostan",
"extensions": [],
"json_metadata": "",
"posting_json_metadata": "{\"profile\":{\"name\":\"Iulian Costan\",\"about\":\"Software developer, derivatives trader, crypto hodler.\",\"website\":\"http://iuliancostan.com\",\"location\":\"Romania\",\"cover_image\":\"https://cdn.steemitimages.com/DQmRDebpsdxEV3eCyhwTw3yzSRVTmqU9nNP4WaxShFX3dmR/avatar-india.jpg\",\"version\":2}}"
}
],
"op_in_trx": 0,
"timestamp": "2020-04-02T04:27:33",
"trx_id": "d9520a989fb3a727cc23f6e4687d95746152e96f",
"trx_in_block": 29,
"virtual_op": 0
}2020/01/01 08:51:03
2020/01/01 08:51:03
| delegatee | icostan |
| delegator | steem |
| vesting shares | 8802.734898 VESTS |
| Transaction Info | Block #39542925/Trx f15b2441f619685e3ebac34fb26dd9137bbe6ee8 |
View Raw JSON Data
{
"block": 39542925,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "8802.734898 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2020-01-01T08:51:03",
"trx_id": "f15b2441f619685e3ebac34fb26dd9137bbe6ee8",
"trx_in_block": 5,
"virtual_op": 0
}2019/10/06 17:54:36
2019/10/06 17:54:36
| author | shtabnoy |
| body | Nice article, very clear |
| json metadata | {"app":"steemit/0.1"} |
| parent author | icostan |
| parent permlink | animated-elliptic-curve-cryptography |
| permlink | pyysey |
| title | |
| Transaction Info | Block #37052957/Trx dbc5bdcb47eb9f1a57ed2b8d03c4bc61ca9d8210 |
View Raw JSON Data
{
"block": 37052957,
"op": [
"comment",
{
"author": "shtabnoy",
"body": "Nice article, very clear",
"json_metadata": "{\"app\":\"steemit/0.1\"}",
"parent_author": "icostan",
"parent_permlink": "animated-elliptic-curve-cryptography",
"permlink": "pyysey",
"title": ""
}
],
"op_in_trx": 0,
"timestamp": "2019-10-06T17:54:36",
"trx_id": "dbc5bdcb47eb9f1a57ed2b8d03c4bc61ca9d8210",
"trx_in_block": 10,
"virtual_op": 0
}shtabnoyupvoted (100.00%) @icostan / animated-elliptic-curve-cryptography2019/10/06 17:54:06
shtabnoyupvoted (100.00%) @icostan / animated-elliptic-curve-cryptography
2019/10/06 17:54:06
| author | icostan |
| permlink | animated-elliptic-curve-cryptography |
| voter | shtabnoy |
| weight | 10000 (100.00%) |
| Transaction Info | Block #37052947/Trx b249e42af25d18db9c3ee73d828ab7451576a9a4 |
View Raw JSON Data
{
"block": 37052947,
"op": [
"vote",
{
"author": "icostan",
"permlink": "animated-elliptic-curve-cryptography",
"voter": "shtabnoy",
"weight": 10000
}
],
"op_in_trx": 0,
"timestamp": "2019-10-06T17:54:06",
"trx_id": "b249e42af25d18db9c3ee73d828ab7451576a9a4",
"trx_in_block": 13,
"virtual_op": 0
}2019/10/02 07:45:42
2019/10/02 07:45:42
| delegatee | icostan |
| delegator | steem |
| vesting shares | 29153.734298 VESTS |
| Transaction Info | Block #36925839/Trx 89ee156ff73f86d7c1799fdeffc12cb75dfa6330 |
View Raw JSON Data
{
"block": 36925839,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "29153.734298 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2019-10-02T07:45:42",
"trx_id": "89ee156ff73f86d7c1799fdeffc12cb75dfa6330",
"trx_in_block": 20,
"virtual_op": 0
}icostanpublished a new post: animated-elliptic-curve-cryptography2019/10/02 07:43:27
icostanpublished a new post: animated-elliptic-curve-cryptography
2019/10/02 07:43:27
| author | icostan |
| body | @@ -800,17 +800,17 @@ point i -f +s the res |
| json metadata | {"tags":["elliptic-curves","sagemath","animation"],"image":["https://cdn.steemitimages.com/DQmeaftKeUgnvojjuNFV6xHeX2mV4S33otD5rPumc78JxnU/ec11-animate.gif"],"links":["https://blog.iuliancostan.com/post/2019-09-25-elliptic-curves/"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | cryptography |
| permlink | animated-elliptic-curve-cryptography |
| title | Animated Elliptic Curve cryptography |
| Transaction Info | Block #36925794/Trx 43ba672527881c58b92f334f64496b9808f3d35d |
View Raw JSON Data
{
"block": 36925794,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -800,17 +800,17 @@\n point i\n-f\n+s\n the res\n",
"json_metadata": "{\"tags\":[\"elliptic-curves\",\"sagemath\",\"animation\"],\"image\":[\"https://cdn.steemitimages.com/DQmeaftKeUgnvojjuNFV6xHeX2mV4S33otD5rPumc78JxnU/ec11-animate.gif\"],\"links\":[\"https://blog.iuliancostan.com/post/2019-09-25-elliptic-curves/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "cryptography",
"permlink": "animated-elliptic-curve-cryptography",
"title": "Animated Elliptic Curve cryptography"
}
],
"op_in_trx": 0,
"timestamp": "2019-10-02T07:43:27",
"trx_id": "43ba672527881c58b92f334f64496b9808f3d35d",
"trx_in_block": 7,
"virtual_op": 0
}icostanpublished a new post: animated-elliptic-curve-cryptography2019/10/02 07:20:06
icostanpublished a new post: animated-elliptic-curve-cryptography
2019/10/02 07:20:06
| author | icostan |
| body | The easiest way to understand Elliptic Curve (EC), point addition, scalar multiplication and trapdoor function; explained with simple graphs and animations. # 1. Abstract - What the heck is an elliptic curve? - A plane algebraic curve defined by an equation of this form: ***y<sup>2</sup> = x<sup>3</sup> + a\*x + b*** - Why are elliptic curves important in cryptography? - Because elliptic curve scalar multiplication is a trapdoor function - How does scalar multiplication works? - Scalar/point multiplication is defined as repeated addition of a point to itself - How does point addition works then? - If we draw a line passing thru elliptic curve points (or draw a tangent to a single point) it will intersect another point on the curve and the inverse of this intersection point if the result of point addition Since a picture is worth a thousand words then the following elliptic curve point addition/multiplication animation has 33 frames and is worth a lot more, do the math.  Given an elliptic curve ***E*** a point on elliptic curve ***G*** (called the generator) and a private key ***k*** we can calculate the public key ***P*** where ***P = k \* G***. The whole idea behind elliptic curves cryptography is that point addition (multiplication) is a trapdoor function which means that given ***G*** and ***P*** points it is infeasible to find the private key ***k***. [Read the blog post](https://blog.iuliancostan.com/post/2019-09-25-elliptic-curves/) for more details. |
| json metadata | {"tags":["cryptography","elliptic-curves","sagemath","animation"],"image":["https://cdn.steemitimages.com/DQmeaftKeUgnvojjuNFV6xHeX2mV4S33otD5rPumc78JxnU/ec11-animate.gif"],"links":["https://blog.iuliancostan.com/post/2019-09-25-elliptic-curves/"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | cryptography |
| permlink | animated-elliptic-curve-cryptography |
| title | Animated Elliptic Curve cryptography |
| Transaction Info | Block #36925327/Trx 981ed93f58da6cd9c6bc72313d57ae1d04ba7819 |
View Raw JSON Data
{
"block": 36925327,
"op": [
"comment",
{
"author": "icostan",
"body": "The easiest way to understand Elliptic Curve (EC), point addition, scalar multiplication and trapdoor function; explained with simple graphs and animations.\n\n\n# 1. Abstract\n\n- What the heck is an elliptic curve?\n- A plane algebraic curve defined by an equation of this form: ***y<sup>2</sup> = x<sup>3</sup> + a\\*x + b***\n\n- Why are elliptic curves important in cryptography?\n- Because elliptic curve scalar multiplication is a trapdoor function\n\n- How does scalar multiplication works?\n- Scalar/point multiplication is defined as repeated addition of a point to itself\n\n- How does point addition works then?\n- If we draw a line passing thru elliptic curve points (or draw a tangent to a single point) it will intersect another point on the curve and the inverse of this intersection point if the result of point addition\n\nSince a picture is worth a thousand words then the following elliptic curve point addition/multiplication animation has 33 frames and is worth a lot more, do the math.\n\n\n\nGiven an elliptic curve ***E*** a point on elliptic curve ***G*** (called the generator) and a private key ***k*** we can calculate the public key ***P*** where ***P = k \\* G***.\n\nThe whole idea behind elliptic curves cryptography is that point addition (multiplication) is a trapdoor function which means that given ***G*** and ***P*** points it is infeasible to find the private key ***k***.\n\n[Read the blog post](https://blog.iuliancostan.com/post/2019-09-25-elliptic-curves/) for more details.",
"json_metadata": "{\"tags\":[\"cryptography\",\"elliptic-curves\",\"sagemath\",\"animation\"],\"image\":[\"https://cdn.steemitimages.com/DQmeaftKeUgnvojjuNFV6xHeX2mV4S33otD5rPumc78JxnU/ec11-animate.gif\"],\"links\":[\"https://blog.iuliancostan.com/post/2019-09-25-elliptic-curves/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "cryptography",
"permlink": "animated-elliptic-curve-cryptography",
"title": "Animated Elliptic Curve cryptography"
}
],
"op_in_trx": 0,
"timestamp": "2019-10-02T07:20:06",
"trx_id": "981ed93f58da6cd9c6bc72313d57ae1d04ba7819",
"trx_in_block": 2,
"virtual_op": 0
}icostanupdated their account properties2019/10/01 19:17:18
icostanupdated their account properties
2019/10/01 19:17:18
| account | icostan |
| json metadata | {"profile":{"name":"Iulian Costan","about":"Computer geek, derivatives trader, crypto hodler.","website":"http://iuliancostan.com","location":"Romania"}} |
| memo key | STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa |
| Transaction Info | Block #36910901/Trx 4f997334884fc80d747648ca940bad998c6f1989 |
View Raw JSON Data
{
"block": 36910901,
"op": [
"account_update",
{
"account": "icostan",
"json_metadata": "{\"profile\":{\"name\":\"Iulian Costan\",\"about\":\"Computer geek, derivatives trader, crypto hodler.\",\"website\":\"http://iuliancostan.com\",\"location\":\"Romania\"}}",
"memo_key": "STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa"
}
],
"op_in_trx": 0,
"timestamp": "2019-10-01T19:17:18",
"trx_id": "4f997334884fc80d747648ca940bad998c6f1989",
"trx_in_block": 6,
"virtual_op": 0
}icostanupdated their account properties2019/10/01 19:17:06
icostanupdated their account properties
2019/10/01 19:17:06
| account | icostan |
| json metadata | {"profile":{"name":"Iulian Costan","about":"Computer geek, derivatives trader, crypto hodler.","website":"http://iuliancostan.com"}} |
| memo key | STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa |
| Transaction Info | Block #36910897/Trx 6635ed8a425fca74232a11eca8603cbfbfe93e32 |
View Raw JSON Data
{
"block": 36910897,
"op": [
"account_update",
{
"account": "icostan",
"json_metadata": "{\"profile\":{\"name\":\"Iulian Costan\",\"about\":\"Computer geek, derivatives trader, crypto hodler.\",\"website\":\"http://iuliancostan.com\"}}",
"memo_key": "STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa"
}
],
"op_in_trx": 0,
"timestamp": "2019-10-01T19:17:06",
"trx_id": "6635ed8a425fca74232a11eca8603cbfbfe93e32",
"trx_in_block": 30,
"virtual_op": 0
}2019/08/22 17:00:03
2019/08/22 17:00:03
| amount | 0.001 STEEM |
| from | dtube |
| memo | Time is running out, claim your DTube account now before anyone else can! Login at https://d.tube |
| to | icostan |
| Transaction Info | Block #35780410/Trx cb772d3bbec3755241820bb4cd7e5554c5b8760c |
View Raw JSON Data
{
"block": 35780410,
"op": [
"transfer",
{
"amount": "0.001 STEEM",
"from": "dtube",
"memo": "Time is running out, claim your DTube account now before anyone else can! Login at https://d.tube",
"to": "icostan"
}
],
"op_in_trx": 0,
"timestamp": "2019-08-22T17:00:03",
"trx_id": "cb772d3bbec3755241820bb4cd7e5554c5b8760c",
"trx_in_block": 26,
"virtual_op": 0
}2019/07/13 22:21:45
2019/07/13 22:21:45
| author | steemitboard |
| body | Congratulations @icostan! You received a personal award! <table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@icostan/birthday2.png</td><td>Happy Birthday! - You are on the Steem blockchain for 2 years!</td></tr></table> <sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@icostan) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=icostan)_</sub> > You can upvote this notification to help all Steem users. Learn how [here](https://steemit.com/steemitboard/@steemitboard/http-i-cubeupload-com-7ciqeo-png)! |
| json metadata | {"image":["https://steemitboard.com/img/notify.png"]} |
| parent author | icostan |
| parent permlink | cryptography-ecdsa |
| permlink | steemitboard-notify-icostan-20190713t222144000z |
| title | |
| Transaction Info | Block #34637890/Trx ab7540f837d96615d1d8fc332584bc9e844036e2 |
View Raw JSON Data
{
"block": 34637890,
"op": [
"comment",
{
"author": "steemitboard",
"body": "Congratulations @icostan! You received a personal award!\n\n<table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@icostan/birthday2.png</td><td>Happy Birthday! - You are on the Steem blockchain for 2 years!</td></tr></table>\n\n<sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@icostan) and compare to others on the [Steem Ranking](https://steemitboard.com/ranking/index.php?name=icostan)_</sub>\n\n\n> You can upvote this notification to help all Steem users. Learn how [here](https://steemit.com/steemitboard/@steemitboard/http-i-cubeupload-com-7ciqeo-png)!",
"json_metadata": "{\"image\":[\"https://steemitboard.com/img/notify.png\"]}",
"parent_author": "icostan",
"parent_permlink": "cryptography-ecdsa",
"permlink": "steemitboard-notify-icostan-20190713t222144000z",
"title": ""
}
],
"op_in_trx": 0,
"timestamp": "2019-07-13T22:21:45",
"trx_id": "ab7540f837d96615d1d8fc332584bc9e844036e2",
"trx_in_block": 0,
"virtual_op": 0
}2019/07/13 13:28:51
2019/07/13 13:28:51
| delegatee | icostan |
| delegator | steem |
| vesting shares | 8904.899509 VESTS |
| Transaction Info | Block #34627241/Trx 645ad8516606a7748c958afff3fbad6f9562fa20 |
View Raw JSON Data
{
"block": 34627241,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "8904.899509 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2019-07-13T13:28:51",
"trx_id": "645ad8516606a7748c958afff3fbad6f9562fa20",
"trx_in_block": 26,
"virtual_op": 0
}2019/06/02 00:01:18
2019/06/02 00:01:18
| delegatee | icostan |
| delegator | steem |
| vesting shares | 28854.534201 VESTS |
| Transaction Info | Block #33431975/Trx 3b73f4617fad11d97ebf6f5eb391db5ffbf6495c |
View Raw JSON Data
{
"block": 33431975,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "28854.534201 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2019-06-02T00:01:18",
"trx_id": "3b73f4617fad11d97ebf6f5eb391db5ffbf6495c",
"trx_in_block": 27,
"virtual_op": 0
}2019/04/13 13:20:09
2019/04/13 13:20:09
| author | resteemsupport |
| body | Hello icostan! Congratulations! This post has been randomly Resteemed! For a chance to get more of your content resteemed join the [Steem Engine Team](https://steemit.com/steemit/@steemengineteam/more-followers-more-votes-steemengine) |
| json metadata | |
| parent author | icostan |
| parent permlink | eli5-cryptography-elgamal |
| permlink | re-eli5-cryptography-elgamal-20190413t132006 |
| title | |
| Transaction Info | Block #32008862/Trx 30ca621925910a808c10ada642361674e250a481 |
View Raw JSON Data
{
"block": 32008862,
"op": [
"comment",
{
"author": "resteemsupport",
"body": "Hello icostan!\n\nCongratulations! This post has been randomly Resteemed! For a chance to get more of your content resteemed join the [Steem Engine Team](https://steemit.com/steemit/@steemengineteam/more-followers-more-votes-steemengine)",
"json_metadata": "",
"parent_author": "icostan",
"parent_permlink": "eli5-cryptography-elgamal",
"permlink": "re-eli5-cryptography-elgamal-20190413t132006",
"title": ""
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:20:09",
"trx_id": "30ca621925910a808c10ada642361674e250a481",
"trx_in_block": 7,
"virtual_op": 0
}icostanpublished a new post: cryptography-ecdsa2019/04/13 13:19:51
icostanpublished a new post: cryptography-ecdsa
2019/04/13 13:19:51
| author | icostan |
| body | @@ -1612,16 +1612,19 @@ Basics%0A +--- %0A- Wha @@ -3752,16 +3752,19 @@ gnature%0A +--- %0ALet's s @@ -4383,16 +4383,19 @@ ication%0A +--- %0AGiven t @@ -4930,16 +4930,19 @@ tuition%0A +--- %0ARemembe |
| json metadata | {"tags":["ecdsa","cryptography","discrete","logarithm"],"links":["https://en.wikipedia.org/wiki/Elliptic-curve_cryptography","https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm","http://www.sagemath.org","https://en.wikipedia.org/wiki/Multiplicative_inverse","https://en.wikipedia.org/wiki/Trapdoor_function"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | ecdsa |
| permlink | cryptography-ecdsa |
| title | Cryptography: ECDSA |
| Transaction Info | Block #32008856/Trx 465fb3219587d8040e51f81e2d48d1f52b2ad510 |
View Raw JSON Data
{
"block": 32008856,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -1612,16 +1612,19 @@\n Basics%0A\n+---\n %0A- Wha\n@@ -3752,16 +3752,19 @@\n gnature%0A\n+---\n %0ALet's s\n@@ -4383,16 +4383,19 @@\n ication%0A\n+---\n %0AGiven t\n@@ -4930,16 +4930,19 @@\n tuition%0A\n+---\n %0ARemembe\n",
"json_metadata": "{\"tags\":[\"ecdsa\",\"cryptography\",\"discrete\",\"logarithm\"],\"links\":[\"https://en.wikipedia.org/wiki/Elliptic-curve_cryptography\",\"https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm\",\"http://www.sagemath.org\",\"https://en.wikipedia.org/wiki/Multiplicative_inverse\",\"https://en.wikipedia.org/wiki/Trapdoor_function\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "ecdsa",
"permlink": "cryptography-ecdsa",
"title": "Cryptography: ECDSA"
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:19:51",
"trx_id": "465fb3219587d8040e51f81e2d48d1f52b2ad510",
"trx_in_block": 14,
"virtual_op": 0
}icostanpublished a new post: eli5-cryptography-elgamal2019/04/13 13:19:06
icostanpublished a new post: eli5-cryptography-elgamal
2019/04/13 13:19:06
| author | icostan |
| body | @@ -1133,16 +1133,19 @@ rapdoor%0A +--- %0AFirst t @@ -2751,16 +2751,19 @@ ryption%0A +--- %0A%5C%60m%5C%60 i @@ -3085,16 +3085,19 @@ ryption%0A +--- %0ATo decr @@ -3981,16 +3981,19 @@ tuition%0A +--- %0AWhy thi |
| json metadata | {"tags":["cryptography","elgamal","discrete","logarithm","eli5"],"links":["https://en.wikipedia.org/wiki/ElGamal_encryption","https://en.wikipedia.org/wiki/ElGamal_signature_scheme","https://en.wikipedia.org/wiki/Cyclic_group","https://en.wikipedia.org/wiki/Discrete_logarithm","https://en.wikipedia.org/wiki/Additive_inverse","https://en.wikipedia.org/wiki/Finite_field","https://en.wikipedia.org/wiki/Euler%2527s_theorem","https://en.wikipedia.org/wiki/Lagrange%2527s_theorem_(group_theory)"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | cryptography |
| permlink | eli5-cryptography-elgamal |
| title | Cryptography: ElGamal |
| Transaction Info | Block #32008841/Trx bdeeb12143ceba12d919d28819c28a26271ee0b8 |
View Raw JSON Data
{
"block": 32008841,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -1133,16 +1133,19 @@\n rapdoor%0A\n+---\n %0AFirst t\n@@ -2751,16 +2751,19 @@\n ryption%0A\n+---\n %0A%5C%60m%5C%60 i\n@@ -3085,16 +3085,19 @@\n ryption%0A\n+---\n %0ATo decr\n@@ -3981,16 +3981,19 @@\n tuition%0A\n+---\n %0AWhy thi\n",
"json_metadata": "{\"tags\":[\"cryptography\",\"elgamal\",\"discrete\",\"logarithm\",\"eli5\"],\"links\":[\"https://en.wikipedia.org/wiki/ElGamal_encryption\",\"https://en.wikipedia.org/wiki/ElGamal_signature_scheme\",\"https://en.wikipedia.org/wiki/Cyclic_group\",\"https://en.wikipedia.org/wiki/Discrete_logarithm\",\"https://en.wikipedia.org/wiki/Additive_inverse\",\"https://en.wikipedia.org/wiki/Finite_field\",\"https://en.wikipedia.org/wiki/Euler%2527s_theorem\",\"https://en.wikipedia.org/wiki/Lagrange%2527s_theorem_(group_theory)\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "cryptography",
"permlink": "eli5-cryptography-elgamal",
"title": "Cryptography: ElGamal"
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:19:06",
"trx_id": "bdeeb12143ceba12d919d28819c28a26271ee0b8",
"trx_in_block": 0,
"virtual_op": 0
}icostanpublished a new post: eli5-cryptography-rsa2019/04/13 13:18:00
icostanpublished a new post: eli5-cryptography-rsa
2019/04/13 13:18:00
| author | icostan |
| body | @@ -1077,17 +1077,20 @@ rapdoor%0A +--- %0A - The very @@ -2324,17 +2324,20 @@ ryption%0A +--- %0A - Now it's @@ -3364,17 +3364,20 @@ ryption%0A +--- %0A - The %5C%60d%5C @@ -4098,16 +4098,19 @@ tuition%0A +--- %0AAt firs |
| json metadata | {"tags":["cryptography","rsa","primes","factorization","eli5"],"links":["https://en.wikipedia.org/wiki/RSA_(cryptosystem)","https://en.wikipedia.org/wiki/Euler's_totient_function","https://en.wikipedia.org/wiki/Coprime_integers","https://en.wikipedia.org/wiki/Trapdoor_function","https://en.wikipedia.org/wiki/Integer_factorization","https://en.wikipedia.org/wiki/Greatest_common_divisor","https://en.wikipedia.org/wiki/Euclidean_algorithm","https://en.wikipedia.org/wiki/Multiplicative_inverse","https://en.wikipedia.org/wiki/Finite_field","https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | cryptography |
| permlink | eli5-cryptography-rsa |
| title | Cryptography: RSA |
| Transaction Info | Block #32008819/Trx 95c0ac96e6bf66ea3f1340e49da10f6952227a98 |
View Raw JSON Data
{
"block": 32008819,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -1077,17 +1077,20 @@\n rapdoor%0A\n+---\n %0A\n-\n The very\n@@ -2324,17 +2324,20 @@\n ryption%0A\n+---\n %0A\n-\n Now it's\n@@ -3364,17 +3364,20 @@\n ryption%0A\n+---\n %0A\n-\n The %5C%60d%5C\n@@ -4098,16 +4098,19 @@\n tuition%0A\n+---\n %0AAt firs\n",
"json_metadata": "{\"tags\":[\"cryptography\",\"rsa\",\"primes\",\"factorization\",\"eli5\"],\"links\":[\"https://en.wikipedia.org/wiki/RSA_(cryptosystem)\",\"https://en.wikipedia.org/wiki/Euler's_totient_function\",\"https://en.wikipedia.org/wiki/Coprime_integers\",\"https://en.wikipedia.org/wiki/Trapdoor_function\",\"https://en.wikipedia.org/wiki/Integer_factorization\",\"https://en.wikipedia.org/wiki/Greatest_common_divisor\",\"https://en.wikipedia.org/wiki/Euclidean_algorithm\",\"https://en.wikipedia.org/wiki/Multiplicative_inverse\",\"https://en.wikipedia.org/wiki/Finite_field\",\"https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "cryptography",
"permlink": "eli5-cryptography-rsa",
"title": "Cryptography: RSA"
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:18:00",
"trx_id": "95c0ac96e6bf66ea3f1340e49da10f6952227a98",
"trx_in_block": 11,
"virtual_op": 0
}icostanpublished a new post: cryptography-ecdsa2019/04/13 13:16:36
icostanpublished a new post: cryptography-ecdsa
2019/04/13 13:16:36
| author | icostan |
| body | @@ -2303,33 +2303,8 @@ ()%0A%0A -!%5Bimg%5D(/assets/ec1.png)%0A%0A Not @@ -2461,34 +2461,8 @@ ()%0A%0A -!%5Bimg%5D(/assets/ec2.png)%0A%0A%0A # El |
| json metadata | {"tags":["ecdsa","cryptography","discrete","logarithm"],"links":["https://en.wikipedia.org/wiki/Elliptic-curve_cryptography","https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm","http://www.sagemath.org","https://en.wikipedia.org/wiki/Multiplicative_inverse","https://en.wikipedia.org/wiki/Trapdoor_function"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | ecdsa |
| permlink | cryptography-ecdsa |
| title | Cryptography: ECDSA |
| Transaction Info | Block #32008791/Trx b4154570b0007f5f7c6d269ad4571f1f4ddc9f45 |
View Raw JSON Data
{
"block": 32008791,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -2303,33 +2303,8 @@\n ()%0A%0A\n-!%5Bimg%5D(/assets/ec1.png)%0A%0A\n Not \n@@ -2461,34 +2461,8 @@\n ()%0A%0A\n-!%5Bimg%5D(/assets/ec2.png)%0A%0A%0A\n # El\n",
"json_metadata": "{\"tags\":[\"ecdsa\",\"cryptography\",\"discrete\",\"logarithm\"],\"links\":[\"https://en.wikipedia.org/wiki/Elliptic-curve_cryptography\",\"https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm\",\"http://www.sagemath.org\",\"https://en.wikipedia.org/wiki/Multiplicative_inverse\",\"https://en.wikipedia.org/wiki/Trapdoor_function\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "ecdsa",
"permlink": "cryptography-ecdsa",
"title": "Cryptography: ECDSA"
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:16:36",
"trx_id": "b4154570b0007f5f7c6d269ad4571f1f4ddc9f45",
"trx_in_block": 8,
"virtual_op": 0
}icostanpublished a new post: cryptography-ecdsa2019/04/13 13:12:15
icostanpublished a new post: cryptography-ecdsa
2019/04/13 13:12:15
| author | icostan |
| body | # Overview --- "If you can't explain it simply, you don't understand it well enough" - Einstein --- Elliptic curve cryptography ([ECC](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)) and digital signature algorithm ([ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)) are more complex than RSA or ElGamal but I will try my best to hide the hairy math and the implementation details. Here is the ELI5 version in 18 lines of [SageMath](http://www.sagemath.org) / Python code. I use Sage because it provides elliptic curves as first-class citizens (\`FiniteField\` and \`EllipticCurve\`) and we can take multiplication operation for granted. 1 p = 103 2 F = FiniteField(p) 3 E = EllipticCurve(F, [0, 7]) 4 G = E([97, 10]) 5 n = G.order() 6 k = randint(2, n) 7 P = k * G 8 m = 6 9 t = randint(2, n) 10 R = t * G 11 r = mod(R[0], n) 12 s = mod(inverse_mod(t, n) * (m + r * k), n) 13 inv_s = inverse_mod(int(s), n) 14 u = mod(m * inv_s, n) 15 v = mod(r * inv_s, n) 16 F = int(u) * G + int(v) * P 17 f = mod(F[0], n) 18 print "YOU ARE A CRYPTOSTAR!" if r == f else "YOU SUCK!" YOU ARE A CRYPTOSTAR! Besides lines #7, #10 and #16 that involves multiplication between a scalar and a point on elliptic curve, everything else is just modular arithmetic and two [multiplicative inverse](https://en.wikipedia.org/wiki/Multiplicative_inverse) calculations (line #12 and #13) Please keep reading if you want line by line explanations and a few elliptic curve graphs. # Basics - What the heck is an elliptic curve? - It is just a simple equation of this form \`y2 = x3 + ax + b\`. - Why it is so special? - Because it has one interesting operation: addition. Adding two points on the curve will result a third point also on the curve (aka closure). Multiplication is particular case of addition, adding the same point to itself \`k\` times. - And how does it looks like? - Well, I am afraid you won't like the graph because elliptic curves defined over finite fields get cut off and are not intelligible to humans eye But here it is anyway: \`a = 0; b = 7\` and prime number is \`103\`. E = EllipticCurve(FiniteField(103), [0, 7]) E.plot()  Not pretty huh? lets define the same elliptic curve over real numbers and the graph starts to make little sense. E = EllipticCurve([0, 7]) E.plot()  # Elliptic curve multiplication trapdoor First thing first, let's define the elliptic curve parameters and notations: 1 p = 103 2 F = FiniteField(p) 3 E = EllipticCurve(F, [0, 7]) 4 G = E([97, 10]) 5 n = G.order() Variable notations: - uppercase letter - elements of the elliptic curve like finite fields (F), elliptic curve itself (E) or point on elliptic curve (G) - lowercase letter - scalar value like the secret key (k) Domain parameters: - p - prime number - F - finite field - 0,7 - coefficients for elliptic curve - E - elliptic curve - G - point generator - n - order (the number of points) of the cyclic subgroup generated by \`G\` Now, it's time to generate the secret key \`k\` and calculate the public key \`P\` using the trapdoor function called Elliptic Curve Discrete Logarithm Problem (ECDLP). This is the bread and the butter of elliptic curve cryptography, given the generator \`G\` and public key \`P' it is infeasible to calculate the secret key \`k\`, hence the [trapdoor](https://en.wikipedia.org/wiki/Trapdoor_function) 6 k = randint(2, n) 7 P = k * G If you are curious how elliptic curve point \`P\` looks like then it is nothing than a Cartesian (x,y) coordinate: P (65 : 31 : 1) # Signature Let's sign the message \`m\` and for this we need to generate a random integer \`t\` of order \`n\` and calculate the \`R\` point on elliptic curve. 8 m = 6 9 t = randint(2, n) 10 R = t * G 11 r = mod(R[0], n) 12 s = mod(inverse_mod(t, n) * (m + r * k), n) The signature itself has two numbers \`r\` and \`s\` that are sent to third-party for verification: - r - the \`x\` coordinate of point \`R\` - s - is calculated with \`s = (m + r\*k) / t\` but we use multiplication with inverse instead of division. And this is how our signature looks like: [r, s] [66, 51] # Verification Given the signature \`r, s\` above and \`G, P, r and n\` that are public information we need to calculate the equation \`F = u\*G + v\*P\` where \`u = m/s\` and \`v = r/s\`. The signature is valid if \`R.x == F.x\` is true, in other words the \`x\` coordinates are the same. 13 inv_s = inverse_mod(int(s), n) 14 u = mod(m * inv_s, n) 15 v = mod(r * inv_s, n) 16 F = int(u) * G + int(v) * P 17 f = mod(F[0], n) 18 print "YOU ARE A CRYPTOSTAR!" if r == f else "YOU SUCK!" YOU ARE A CRYPTOSTAR! # Intuition Remember that uppercase letters are points on elliptic curve, lowercase are scalars: 1 R == u*G + v*P 2 R == u*G + v*k*P 3 R == m/s * G + r/s * k*G 4 R == m/s * G + r*k/s * G 5 R == (m + r*k)/s * G 6 R == (m + r*k)/((m + r*k)/t) * G As always we will do the math backwards: 1. start with the equation of signature verification and substitute public key \`P\` 2. substitute \`u\` and \`v\` 3. multiplication is commutative and we can put \`r\` and \`k\` together 4. extract \`G\` and \`s\` as factors 5. substitute \`s\` 6. after reduction we are left with \`t\*G\` And the intuition is valid if the \`x\` coordinates on both sides of the equation are equal. print "MAGIC" if R[0] == (int((m + r*k)*t/(m + r*k)) * G)[0] else "ERROR" MAGIC |
| json metadata | {"tags":["cryptography","ecdsa","discrete","logarithm"],"links":["https://en.wikipedia.org/wiki/Elliptic-curve_cryptography","https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm","http://www.sagemath.org","https://en.wikipedia.org/wiki/Multiplicative_inverse","https://en.wikipedia.org/wiki/Trapdoor_function"],"app":"steemit/0.1","format":"markdown","image":["/assets/ec1.png","/assets/ec2.png"]} |
| parent author | |
| parent permlink | ecdsa |
| permlink | cryptography-ecdsa |
| title | Cryptography: ECDSA |
| Transaction Info | Block #32008705/Trx 24e20a1bb7d8ca417bcec8a50f797012fa039eaf |
View Raw JSON Data
{
"block": 32008705,
"op": [
"comment",
{
"author": "icostan",
"body": "# Overview\n---\n\n \"If you can't explain it simply, you don't understand it well enough\" - Einstein\n---\nElliptic curve cryptography ([ECC](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)) and digital signature algorithm ([ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)) are more complex than RSA or ElGamal but I will try my best to hide the hairy math and the implementation details.\n\nHere is the ELI5 version in 18 lines of [SageMath](http://www.sagemath.org) / Python code. I use Sage because it provides elliptic curves as first-class citizens (\\`FiniteField\\` and \\`EllipticCurve\\`) and we can take multiplication operation for granted.\n\n 1 p = 103\n 2 F = FiniteField(p)\n 3 E = EllipticCurve(F, [0, 7])\n 4 G = E([97, 10])\n 5 n = G.order()\n 6 k = randint(2, n)\n 7 P = k * G\n 8 m = 6\n 9 t = randint(2, n)\n 10 R = t * G\n 11 r = mod(R[0], n)\n 12 s = mod(inverse_mod(t, n) * (m + r * k), n)\n 13 inv_s = inverse_mod(int(s), n)\n 14 u = mod(m * inv_s, n)\n 15 v = mod(r * inv_s, n)\n 16 F = int(u) * G + int(v) * P\n 17 f = mod(F[0], n)\n 18 print \"YOU ARE A CRYPTOSTAR!\" if r == f else \"YOU SUCK!\"\n\n YOU ARE A CRYPTOSTAR!\n\nBesides lines #7, #10 and #16 that involves multiplication between a scalar and a point on elliptic curve, everything else is just modular arithmetic and two [multiplicative inverse](https://en.wikipedia.org/wiki/Multiplicative_inverse) calculations (line #12 and #13)\n\nPlease keep reading if you want line by line explanations and a few elliptic curve graphs.\n\n\n# Basics\n\n- What the heck is an elliptic curve?\n- It is just a simple equation of this form \\`y2 = x3 + ax + b\\`.\n- Why it is so special?\n- Because it has one interesting operation: addition. Adding two points on the curve will result a third point also on the curve (aka closure). Multiplication is particular case of addition, adding the same point to itself \\`k\\` times.\n- And how does it looks like?\n- Well, I am afraid you won't like the graph because elliptic curves defined over finite fields get cut off and are not intelligible to humans eye\n\nBut here it is anyway: \\`a = 0; b = 7\\` and prime number is \\`103\\`.\n\n E = EllipticCurve(FiniteField(103), [0, 7])\n E.plot()\n\n\n\nNot pretty huh? lets define the same elliptic curve over real numbers and the graph starts to make little sense.\n\n E = EllipticCurve([0, 7])\n E.plot()\n\n\n\n\n# Elliptic curve multiplication trapdoor\n\nFirst thing first, let's define the elliptic curve parameters and notations:\n\n 1 p = 103\n 2 F = FiniteField(p)\n 3 E = EllipticCurve(F, [0, 7])\n 4 G = E([97, 10])\n 5 n = G.order()\n\nVariable notations:\n\n- uppercase letter - elements of the elliptic curve like finite fields (F), elliptic curve itself (E) or point on elliptic curve (G)\n- lowercase letter - scalar value like the secret key (k)\n\nDomain parameters:\n\n- p - prime number\n- F - finite field\n- 0,7 - coefficients for elliptic curve\n- E - elliptic curve\n- G - point generator\n- n - order (the number of points) of the cyclic subgroup generated by \\`G\\`\n\nNow, it's time to generate the secret key \\`k\\` and calculate the public key \\`P\\` using the trapdoor function called Elliptic Curve Discrete Logarithm Problem (ECDLP).\n\nThis is the bread and the butter of elliptic curve cryptography, given the generator \\`G\\` and public key \\`P' it is infeasible to calculate the secret key \\`k\\`, hence the [trapdoor](https://en.wikipedia.org/wiki/Trapdoor_function)\n\n 6 k = randint(2, n)\n 7 P = k * G\n\nIf you are curious how elliptic curve point \\`P\\` looks like then it is nothing than a Cartesian (x,y) coordinate:\n\n P\n\n (65 : 31 : 1)\n\n\n# Signature\n\nLet's sign the message \\`m\\` and for this we need to generate a random integer \\`t\\` of order \\`n\\` and calculate the \\`R\\` point on elliptic curve.\n\n 8 m = 6\n 9 t = randint(2, n)\n 10 R = t * G\n 11 r = mod(R[0], n)\n 12 s = mod(inverse_mod(t, n) * (m + r * k), n)\n\nThe signature itself has two numbers \\`r\\` and \\`s\\` that are sent to third-party for verification:\n\n- r - the \\`x\\` coordinate of point \\`R\\`\n- s - is calculated with \\`s = (m + r\\*k) / t\\` but we use multiplication with inverse instead of division.\n\nAnd this is how our signature looks like:\n\n [r, s]\n\n [66, 51]\n\n\n# Verification\n\nGiven the signature \\`r, s\\` above and \\`G, P, r and n\\` that are public information we need to calculate the equation \\`F = u\\*G + v\\*P\\` where \\`u = m/s\\` and \\`v = r/s\\`.\n\nThe signature is valid if \\`R.x == F.x\\` is true, in other words the \\`x\\` coordinates are the same.\n\n 13 inv_s = inverse_mod(int(s), n)\n 14 u = mod(m * inv_s, n)\n 15 v = mod(r * inv_s, n)\n 16 F = int(u) * G + int(v) * P\n 17 f = mod(F[0], n)\n 18 print \"YOU ARE A CRYPTOSTAR!\" if r == f else \"YOU SUCK!\"\n\n YOU ARE A CRYPTOSTAR!\n\n\n# Intuition\n\nRemember that uppercase letters are points on elliptic curve, lowercase are scalars:\n\n 1 R == u*G + v*P\n 2 R == u*G + v*k*P\n 3 R == m/s * G + r/s * k*G\n 4 R == m/s * G + r*k/s * G\n 5 R == (m + r*k)/s * G\n 6 R == (m + r*k)/((m + r*k)/t) * G\n\nAs always we will do the math backwards:\n\n1. start with the equation of signature verification and substitute public key \\`P\\`\n2. substitute \\`u\\` and \\`v\\`\n3. multiplication is commutative and we can put \\`r\\` and \\`k\\` together\n4. extract \\`G\\` and \\`s\\` as factors\n5. substitute \\`s\\`\n6. after reduction we are left with \\`t\\*G\\`\n\nAnd the intuition is valid if the \\`x\\` coordinates on both sides of the equation are equal.\n\n print \"MAGIC\" if R[0] == (int((m + r*k)*t/(m + r*k)) * G)[0] else \"ERROR\"\n\n MAGIC",
"json_metadata": "{\"tags\":[\"cryptography\",\"ecdsa\",\"discrete\",\"logarithm\"],\"links\":[\"https://en.wikipedia.org/wiki/Elliptic-curve_cryptography\",\"https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm\",\"http://www.sagemath.org\",\"https://en.wikipedia.org/wiki/Multiplicative_inverse\",\"https://en.wikipedia.org/wiki/Trapdoor_function\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\",\"image\":[\"/assets/ec1.png\",\"/assets/ec2.png\"]}",
"parent_author": "",
"parent_permlink": "ecdsa",
"permlink": "cryptography-ecdsa",
"title": "Cryptography: ECDSA"
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:12:15",
"trx_id": "24e20a1bb7d8ca417bcec8a50f797012fa039eaf",
"trx_in_block": 18,
"virtual_op": 0
}icostanpublished a new post: eli5-cryptography-rsa2019/04/13 13:11:24
icostanpublished a new post: eli5-cryptography-rsa
2019/04/13 13:11:24
| author | icostan |
| body | @@ -4,16 +4,19 @@ verview%0A +--- %0A %22If |
| json metadata | {"tags":["cryptography","rsa","primes","factorization","eli5"],"links":["https://en.wikipedia.org/wiki/RSA_(cryptosystem)","https://en.wikipedia.org/wiki/Euler's_totient_function","https://en.wikipedia.org/wiki/Coprime_integers","https://en.wikipedia.org/wiki/Trapdoor_function","https://en.wikipedia.org/wiki/Integer_factorization","https://en.wikipedia.org/wiki/Greatest_common_divisor","https://en.wikipedia.org/wiki/Euclidean_algorithm","https://en.wikipedia.org/wiki/Multiplicative_inverse","https://en.wikipedia.org/wiki/Finite_field","https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | cryptography |
| permlink | eli5-cryptography-rsa |
| title | Cryptography: RSA |
| Transaction Info | Block #32008688/Trx 71b22b4eb83e9e8b4ae54278b0b4632ea272e69e |
View Raw JSON Data
{
"block": 32008688,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -4,16 +4,19 @@\n verview%0A\n+---\n %0A %22If\n",
"json_metadata": "{\"tags\":[\"cryptography\",\"rsa\",\"primes\",\"factorization\",\"eli5\"],\"links\":[\"https://en.wikipedia.org/wiki/RSA_(cryptosystem)\",\"https://en.wikipedia.org/wiki/Euler's_totient_function\",\"https://en.wikipedia.org/wiki/Coprime_integers\",\"https://en.wikipedia.org/wiki/Trapdoor_function\",\"https://en.wikipedia.org/wiki/Integer_factorization\",\"https://en.wikipedia.org/wiki/Greatest_common_divisor\",\"https://en.wikipedia.org/wiki/Euclidean_algorithm\",\"https://en.wikipedia.org/wiki/Multiplicative_inverse\",\"https://en.wikipedia.org/wiki/Finite_field\",\"https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "cryptography",
"permlink": "eli5-cryptography-rsa",
"title": "Cryptography: RSA"
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:11:24",
"trx_id": "71b22b4eb83e9e8b4ae54278b0b4632ea272e69e",
"trx_in_block": 5,
"virtual_op": 0
}icostanpublished a new post: eli5-cryptography-elgamal2019/04/13 13:10:48
icostanpublished a new post: eli5-cryptography-elgamal
2019/04/13 13:10:48
| author | icostan |
| body | @@ -4,16 +4,19 @@ verview%0A +--- %0A %22If @@ -92,16 +92,20 @@ Einstein +%0A--- %0A%0AElGama |
| json metadata | {"tags":["cryptography","elgamal","discrete","logarithm","eli5"],"links":["https://en.wikipedia.org/wiki/ElGamal_encryption","https://en.wikipedia.org/wiki/ElGamal_signature_scheme","https://en.wikipedia.org/wiki/Cyclic_group","https://en.wikipedia.org/wiki/Discrete_logarithm","https://en.wikipedia.org/wiki/Additive_inverse","https://en.wikipedia.org/wiki/Finite_field","https://en.wikipedia.org/wiki/Euler%2527s_theorem","https://en.wikipedia.org/wiki/Lagrange%2527s_theorem_(group_theory)"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | cryptography |
| permlink | eli5-cryptography-elgamal |
| title | Cryptography: ElGamal |
| Transaction Info | Block #32008676/Trx cc641331f751126d3f588cec2ac1ea401e6d2545 |
View Raw JSON Data
{
"block": 32008676,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -4,16 +4,19 @@\n verview%0A\n+---\n %0A %22If\n@@ -92,16 +92,20 @@\n Einstein\n+%0A---\n %0A%0AElGama\n",
"json_metadata": "{\"tags\":[\"cryptography\",\"elgamal\",\"discrete\",\"logarithm\",\"eli5\"],\"links\":[\"https://en.wikipedia.org/wiki/ElGamal_encryption\",\"https://en.wikipedia.org/wiki/ElGamal_signature_scheme\",\"https://en.wikipedia.org/wiki/Cyclic_group\",\"https://en.wikipedia.org/wiki/Discrete_logarithm\",\"https://en.wikipedia.org/wiki/Additive_inverse\",\"https://en.wikipedia.org/wiki/Finite_field\",\"https://en.wikipedia.org/wiki/Euler%2527s_theorem\",\"https://en.wikipedia.org/wiki/Lagrange%2527s_theorem_(group_theory)\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "cryptography",
"permlink": "eli5-cryptography-elgamal",
"title": "Cryptography: ElGamal"
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:10:48",
"trx_id": "cc641331f751126d3f588cec2ac1ea401e6d2545",
"trx_in_block": 2,
"virtual_op": 0
}icostanpublished a new post: cryptography-ecdsa2019/04/13 13:09:42
icostanpublished a new post: cryptography-ecdsa
2019/04/13 13:09:42
| author | icostan |
| body | # Overview --- "If you can't explain it simply, you don't understand it well enough" - Einstein --- Elliptic curve cryptography ([ECC](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)) and digital signature algorithm ([ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)) are more complex than RSA or ElGamal but I will try my best to hide the hairy math and the implementation details. Here is the ELI5 version in 18 lines of [SageMath](http://www.sagemath.org) / Python code. I use Sage because it provides elliptic curves as first-class citizens (\`FiniteField\` and \`EllipticCurve\`) and we can take multiplication operation for granted. 1 p = 103 2 F = FiniteField(p) 3 E = EllipticCurve(F, [0, 7]) 4 G = E([97, 10]) 5 n = G.order() 6 k = randint(2, n) 7 P = k * G 8 m = 6 9 t = randint(2, n) 10 R = t * G 11 r = mod(R[0], n) 12 s = mod(inverse_mod(t, n) * (m + r * k), n) 13 inv_s = inverse_mod(int(s), n) 14 u = mod(m * inv_s, n) 15 v = mod(r * inv_s, n) 16 F = int(u) * G + int(v) * P 17 f = mod(F[0], n) 18 print "YOU ARE A CRYPTOSTAR!" if r == f else "YOU SUCK!" YOU ARE A CRYPTOSTAR! Besides lines #7, #10 and #16 that involves multiplication between a scalar and a point on elliptic curve, everything else is just modular arithmetic and two [multiplicative inverse](https://en.wikipedia.org/wiki/Multiplicative_inverse) calculations (line #12 and #13) Please keep reading if you want line by line explanations and a few elliptic curve graphs. # Basics - What the heck is an elliptic curve? - It is just a simple equation of this form \`y2 = x3 + ax + b\`. - Why it is so special? - Because it has one interesting operation: addition. Adding two points on the curve will result a third point also on the curve (aka closure). Multiplication is particular case of addition, adding the same point to itself \`k\` times. - And how does it looks like? - Well, I am afraid you won't like the graph because elliptic curves defined over finite fields get cut off and are not intelligible to humans eye But here it is anyway: \`a = 0; b = 7\` and prime number is \`103\`. E = EllipticCurve(FiniteField(103), [0, 7]) E.plot()  Not pretty huh? lets define the same elliptic curve over real numbers and the graph starts to make little sense. E = EllipticCurve([0, 7]) E.plot()  # Elliptic curve multiplication trapdoor First thing first, let's define the elliptic curve parameters and notations: 1 p = 103 2 F = FiniteField(p) 3 E = EllipticCurve(F, [0, 7]) 4 G = E([97, 10]) 5 n = G.order() Variable notations: - uppercase letter - elements of the elliptic curve like finite fields (F), elliptic curve itself (E) or point on elliptic curve (G) - lowercase letter - scalar value like the secret key (k) Domain parameters: - p - prime number - F - finite field - 0,7 - coefficients for elliptic curve - E - elliptic curve - G - point generator - n - order (the number of points) of the cyclic subgroup generated by \`G\` Now, it's time to generate the secret key \`k\` and calculate the public key \`P\` using the trapdoor function called Elliptic Curve Discrete Logarithm Problem (ECDLP). This is the bread and the butter of elliptic curve cryptography, given the generator \`G\` and public key \`P' it is infeasible to calculate the secret key \`k\`, hence the [trapdoor](https://en.wikipedia.org/wiki/Trapdoor_function) 6 k = randint(2, n) 7 P = k * G If you are curious how elliptic curve point \`P\` looks like then it is nothing than a Cartesian (x,y) coordinate: P (65 : 31 : 1) # Signature Let's sign the message \`m\` and for this we need to generate a random integer \`t\` of order \`n\` and calculate the \`R\` point on elliptic curve. 8 m = 6 9 t = randint(2, n) 10 R = t * G 11 r = mod(R[0], n) 12 s = mod(inverse_mod(t, n) * (m + r * k), n) The signature itself has two numbers \`r\` and \`s\` that are sent to third-party for verification: - r - the \`x\` coordinate of point \`R\` - s - is calculated with \`s = (m + r\*k) / t\` but we use multiplication with inverse instead of division. And this is how our signature looks like: [r, s] [66, 51] # Verification Given the signature \`r, s\` above and \`G, P, r and n\` that are public information we need to calculate the equation \`F = u\*G + v\*P\` where \`u = m/s\` and \`v = r/s\`. The signature is valid if \`R.x == F.x\` is true, in other words the \`x\` coordinates are the same. 13 inv_s = inverse_mod(int(s), n) 14 u = mod(m * inv_s, n) 15 v = mod(r * inv_s, n) 16 F = int(u) * G + int(v) * P 17 f = mod(F[0], n) 18 print "YOU ARE A CRYPTOSTAR!" if r == f else "YOU SUCK!" YOU ARE A CRYPTOSTAR! # Intuition Remember that uppercase letters are points on elliptic curve, lowercase are scalars: 1 R == u*G + v*P 2 R == u*G + v*k*P 3 R == m/s * G + r/s * k*G 4 R == m/s * G + r*k/s * G 5 R == (m + r*k)/s * G 6 R == (m + r*k)/((m + r*k)/t) * G As always we will do the math backwards: 1. start with the equation of signature verification and substitute public key \`P\` 2. substitute \`u\` and \`v\` 3. multiplication is commutative and we can put \`r\` and \`k\` together 4. extract \`G\` and \`s\` as factors 5. substitute \`s\` 6. after reduction we are left with \`t\*G\` And the intuition is valid if the \`x\` coordinates on both sides of the equation are equal. print "MAGIC" if R[0] == (int((m + r*k)*t/(m + r*k)) * G)[0] else "ERROR" MAGIC |
| json metadata | {"tags":["ecdsa","cryptography","python","ecc"],"image":["/assets/ec1.png","/assets/ec2.png"],"links":["https://en.wikipedia.org/wiki/Elliptic-curve_cryptography","https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm","http://www.sagemath.org","https://en.wikipedia.org/wiki/Multiplicative_inverse","https://en.wikipedia.org/wiki/Trapdoor_function"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | ecdsa |
| permlink | cryptography-ecdsa |
| title | Cryptography: ECDSA |
| Transaction Info | Block #32008654/Trx ad5c64ceb30d7f8615a6e50baab933220cd14116 |
View Raw JSON Data
{
"block": 32008654,
"op": [
"comment",
{
"author": "icostan",
"body": "# Overview\n---\n\n \"If you can't explain it simply, you don't understand it well enough\" - Einstein\n---\nElliptic curve cryptography ([ECC](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)) and digital signature algorithm ([ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)) are more complex than RSA or ElGamal but I will try my best to hide the hairy math and the implementation details.\n\nHere is the ELI5 version in 18 lines of [SageMath](http://www.sagemath.org) / Python code. I use Sage because it provides elliptic curves as first-class citizens (\\`FiniteField\\` and \\`EllipticCurve\\`) and we can take multiplication operation for granted.\n\n 1 p = 103\n 2 F = FiniteField(p)\n 3 E = EllipticCurve(F, [0, 7])\n 4 G = E([97, 10])\n 5 n = G.order()\n 6 k = randint(2, n)\n 7 P = k * G\n 8 m = 6\n 9 t = randint(2, n)\n 10 R = t * G\n 11 r = mod(R[0], n)\n 12 s = mod(inverse_mod(t, n) * (m + r * k), n)\n 13 inv_s = inverse_mod(int(s), n)\n 14 u = mod(m * inv_s, n)\n 15 v = mod(r * inv_s, n)\n 16 F = int(u) * G + int(v) * P\n 17 f = mod(F[0], n)\n 18 print \"YOU ARE A CRYPTOSTAR!\" if r == f else \"YOU SUCK!\"\n\n YOU ARE A CRYPTOSTAR!\n\nBesides lines #7, #10 and #16 that involves multiplication between a scalar and a point on elliptic curve, everything else is just modular arithmetic and two [multiplicative inverse](https://en.wikipedia.org/wiki/Multiplicative_inverse) calculations (line #12 and #13)\n\nPlease keep reading if you want line by line explanations and a few elliptic curve graphs.\n\n\n# Basics\n\n- What the heck is an elliptic curve?\n- It is just a simple equation of this form \\`y2 = x3 + ax + b\\`.\n- Why it is so special?\n- Because it has one interesting operation: addition. Adding two points on the curve will result a third point also on the curve (aka closure). Multiplication is particular case of addition, adding the same point to itself \\`k\\` times.\n- And how does it looks like?\n- Well, I am afraid you won't like the graph because elliptic curves defined over finite fields get cut off and are not intelligible to humans eye\n\nBut here it is anyway: \\`a = 0; b = 7\\` and prime number is \\`103\\`.\n\n E = EllipticCurve(FiniteField(103), [0, 7])\n E.plot()\n\n\n\nNot pretty huh? lets define the same elliptic curve over real numbers and the graph starts to make little sense.\n\n E = EllipticCurve([0, 7])\n E.plot()\n\n\n\n\n# Elliptic curve multiplication trapdoor\n\nFirst thing first, let's define the elliptic curve parameters and notations:\n\n 1 p = 103\n 2 F = FiniteField(p)\n 3 E = EllipticCurve(F, [0, 7])\n 4 G = E([97, 10])\n 5 n = G.order()\n\nVariable notations:\n\n- uppercase letter - elements of the elliptic curve like finite fields (F), elliptic curve itself (E) or point on elliptic curve (G)\n- lowercase letter - scalar value like the secret key (k)\n\nDomain parameters:\n\n- p - prime number\n- F - finite field\n- 0,7 - coefficients for elliptic curve\n- E - elliptic curve\n- G - point generator\n- n - order (the number of points) of the cyclic subgroup generated by \\`G\\`\n\nNow, it's time to generate the secret key \\`k\\` and calculate the public key \\`P\\` using the trapdoor function called Elliptic Curve Discrete Logarithm Problem (ECDLP).\n\nThis is the bread and the butter of elliptic curve cryptography, given the generator \\`G\\` and public key \\`P' it is infeasible to calculate the secret key \\`k\\`, hence the [trapdoor](https://en.wikipedia.org/wiki/Trapdoor_function)\n\n 6 k = randint(2, n)\n 7 P = k * G\n\nIf you are curious how elliptic curve point \\`P\\` looks like then it is nothing than a Cartesian (x,y) coordinate:\n\n P\n\n (65 : 31 : 1)\n\n\n# Signature\n\nLet's sign the message \\`m\\` and for this we need to generate a random integer \\`t\\` of order \\`n\\` and calculate the \\`R\\` point on elliptic curve.\n\n 8 m = 6\n 9 t = randint(2, n)\n 10 R = t * G\n 11 r = mod(R[0], n)\n 12 s = mod(inverse_mod(t, n) * (m + r * k), n)\n\nThe signature itself has two numbers \\`r\\` and \\`s\\` that are sent to third-party for verification:\n\n- r - the \\`x\\` coordinate of point \\`R\\`\n- s - is calculated with \\`s = (m + r\\*k) / t\\` but we use multiplication with inverse instead of division.\n\nAnd this is how our signature looks like:\n\n [r, s]\n\n [66, 51]\n\n\n# Verification\n\nGiven the signature \\`r, s\\` above and \\`G, P, r and n\\` that are public information we need to calculate the equation \\`F = u\\*G + v\\*P\\` where \\`u = m/s\\` and \\`v = r/s\\`.\n\nThe signature is valid if \\`R.x == F.x\\` is true, in other words the \\`x\\` coordinates are the same.\n\n 13 inv_s = inverse_mod(int(s), n)\n 14 u = mod(m * inv_s, n)\n 15 v = mod(r * inv_s, n)\n 16 F = int(u) * G + int(v) * P\n 17 f = mod(F[0], n)\n 18 print \"YOU ARE A CRYPTOSTAR!\" if r == f else \"YOU SUCK!\"\n\n YOU ARE A CRYPTOSTAR!\n\n\n# Intuition\n\nRemember that uppercase letters are points on elliptic curve, lowercase are scalars:\n\n 1 R == u*G + v*P\n 2 R == u*G + v*k*P\n 3 R == m/s * G + r/s * k*G\n 4 R == m/s * G + r*k/s * G\n 5 R == (m + r*k)/s * G\n 6 R == (m + r*k)/((m + r*k)/t) * G\n\nAs always we will do the math backwards:\n\n1. start with the equation of signature verification and substitute public key \\`P\\`\n2. substitute \\`u\\` and \\`v\\`\n3. multiplication is commutative and we can put \\`r\\` and \\`k\\` together\n4. extract \\`G\\` and \\`s\\` as factors\n5. substitute \\`s\\`\n6. after reduction we are left with \\`t\\*G\\`\n\nAnd the intuition is valid if the \\`x\\` coordinates on both sides of the equation are equal.\n\n print \"MAGIC\" if R[0] == (int((m + r*k)*t/(m + r*k)) * G)[0] else \"ERROR\"\n\n MAGIC",
"json_metadata": "{\"tags\":[\"ecdsa\",\"cryptography\",\"python\",\"ecc\"],\"image\":[\"/assets/ec1.png\",\"/assets/ec2.png\"],\"links\":[\"https://en.wikipedia.org/wiki/Elliptic-curve_cryptography\",\"https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm\",\"http://www.sagemath.org\",\"https://en.wikipedia.org/wiki/Multiplicative_inverse\",\"https://en.wikipedia.org/wiki/Trapdoor_function\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "ecdsa",
"permlink": "cryptography-ecdsa",
"title": "Cryptography: ECDSA"
}
],
"op_in_trx": 0,
"timestamp": "2019-04-13T13:09:42",
"trx_id": "ad5c64ceb30d7f8615a6e50baab933220cd14116",
"trx_in_block": 12,
"virtual_op": 0
}icostanpublished a new post: eli5-cryptography-elgamal2019/03/27 13:27:09
icostanpublished a new post: eli5-cryptography-elgamal
2019/03/27 13:27:09
| author | icostan |
| body | # Overview "If you can't explain it simply, you don't understand it well enough" - Einstein ElGamal is a public key cryptosystem that is used in [encryption](https://en.wikipedia.org/wiki/ElGamal_encryption) , [digital signature](https://en.wikipedia.org/wiki/ElGamal_signature_scheme) and homomorphic cryptography. Here is my take in 12 lines of Python code: 1 p = 7 2 g = [x for x in range(1, p) if len(set([x**i % p for i in range(1, p)])) == p-1][0] 3 k = 4 4 t = g**k % p 5 m = 6 6 import random 7 r = random.randint(1, p-1) 8 c1 = g**r % p 9 c2 = (t**r * m) % p 10 inv_k = p - 1 - k 11 inv_c1 = c1**inv_k % p 12 message = c2 * inv_c1 % p 13 print "YOU ARE A CRYPTOSTAR!" if message == m else "ERROR" YOU ARE A CRYPTOSTAR! Besides line #2 that involves an algorithm to find the generator \`g\` and line #10 that calculates the additive inverse of private key \`k\`, everything else is just modular multiplication and exponentiation. Interested in more details and line by line explanations? please read on. # Discrete logarithm trapdoor First thing first, lets pick a prime number: 1 p = 7 For the prime number above we need to find the generator \`g\` that defines a [cyclic group](https://en.wikipedia.org/wiki/Cyclic_group) which in theory is a little bit involved but in simple terms the generator is a specific number that returns unique values for each exponent between \`1\` and \`p-1\` where \`p-1\` is called the order of the cyclic group. Lets take a few examples and see how it looks like: pick \`2\` as generator: print [2**i % p for i in range(1, p)] [2, 4, 1, 2, 4, 1] We can easily see that returning values are not unique, lets pick \`3\` as generator: print [3**i % p for i in range(1, p)] [3, 2, 6, 4, 5, 1] BINGO! returning values are unique and we've found our generator. The line below is just a brute force algorithm that finds multiple generators of order \`p-1\` but only takes the first one that is found. 2 g = [x for x in range(1, p) if len(set([x**i % p for i in range(1, p)])) == p-1][0] Now is time to pick a private key \`k\` between \`1\` and \`p-1\`, execute the trapdoor function and calculate \`t\` value: 3 k = 4 4 t = g**k % p The line #4 is the secret sauce of ElGamal cryptography, the trapdoor function called [**the discrete logarithm**](https://en.wikipedia.org/wiki/Discrete_logarithm) which says that for given \`g\` and \`t\` values it is **infeasible** to calculate the private key \`k\` when working with very large numbers. The \`p, g and t\` form the public key and will be used in encryption below, while \`k\` is kept secret. # Message encryption \`m\` is the message that we want to encrypt and \`r\` is a random number between \`1\` and \`p-1\`: 5 m = 6 6 import random 7 r = random.randint(1, p-1) 8 c1 = g**r % p 9 c2 = (t**r * m) % p \`c1, c2\` are the encrypted ciphers that will be used to decrypt the original message. # Message decryption To decrypt the original message we need apply the following formula: \`message = c2 / c1<sup>k</sup> mod p\` The problem is that division is not an operation defined for finite fields but multiplication is and we can re-write it using multiplication / exponentiation operations only: \`message = c2 \* c1<sup>inv</sup><sub>k</sub> mod p\` \`inv<sub>k</sub>\` is called [additive inverse](https://en.wikipedia.org/wiki/Additive_inverse) of \`k\` over [finite field](https://en.wikipedia.org/wiki/Finite_field) 'p' where \`k + inv<sub>k</sub> mod p = 0\` is valid. We can brute force and find it but there is a simpler way: if \`k < p\` (which it is) then \`inv<sub>k</sub> = p - 1 - k\`. 10 inv_k = p - 1 - k 11 inv_c1 = c1**inv_k % p 12 message = c2 * inv_c1 % p 13 print "YOU ARE A CRYPTOSTAR!" if message == m else "ERROR" YOU ARE A CRYPTOSTAR! # Intuition Why this magic works the way it works? 1 message == (c2 * inv_c1) % p 2 message == (c2 * c1**(p-1-k)) % p 3 message == (t**r * m * (g**r)**(p-1-k)) % p 4 message == ((g**k)**r * m * (g**r)**(p-1-k)) % p 5 message == (g**(k*r) * m * (g**(r*(p-1-k)))) % p 6 message == (g**(k*r) * m * g**(r*(p-1)) * g**(-r*k)) % p Lets do the math backwards: 1. start with last decryption formula and substitute inverses \`inv<sub>c1</sub>\` and \`inv<sub>k</sub>\` 2. substitute ciphers \`c1\` and \`c2\` 3. substitute trapdoor \`t\` 4. apply exponentiation power rule \`(a<sup>b</sup>)<sup>c</sup> = a<sup>(b\*c)</sup>\` 5. distribute the exponent \`r\` 6. - \`g\*\*(r\*(p-1))\` is 1 because of [Euler's theorem](https://en.wikipedia.org/wiki/Euler%2527s_theorem) and [Lagrange's theorem](https://en.wikipedia.org/wiki/Lagrange%2527s_theorem_(group_theory)) - \`g\*\*(k\*r)\` terms reduces each other Check if the intuition is valid by substituting with numbers: generator \`g\` is 3, private key \`k\` is 4, random number \`r\` is 5 and message \`m\` is 6: print "MAGIC" if 6 == (3**(4*5) * 6 * 3**(5*(7-1)) * 3**(-5*4)) % 7 else "ERROR" MAGIC |
| json metadata | {"tags":["cryptography","elgamal","discrete","logarithm","eli5"],"links":["https://en.wikipedia.org/wiki/ElGamal_encryption","https://en.wikipedia.org/wiki/ElGamal_signature_scheme","https://en.wikipedia.org/wiki/Cyclic_group","https://en.wikipedia.org/wiki/Discrete_logarithm","https://en.wikipedia.org/wiki/Additive_inverse","https://en.wikipedia.org/wiki/Finite_field","https://en.wikipedia.org/wiki/Euler%2527s_theorem","https://en.wikipedia.org/wiki/Lagrange%2527s_theorem_(group_theory)"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | cryptography |
| permlink | eli5-cryptography-elgamal |
| title | ELI5: Cryptography - ElGamal |
| Transaction Info | Block #31521289/Trx c7450e9258272e819fb52141040f589b74abc18c |
View Raw JSON Data
{
"block": 31521289,
"op": [
"comment",
{
"author": "icostan",
"body": "# Overview\n\n \"If you can't explain it simply, you don't understand it well enough\" - Einstein\n\nElGamal is a public key cryptosystem that is used in [encryption](https://en.wikipedia.org/wiki/ElGamal_encryption) , [digital signature](https://en.wikipedia.org/wiki/ElGamal_signature_scheme) and homomorphic cryptography.\n\nHere is my take in 12 lines of Python code:\n\n 1 p = 7\n 2 g = [x for x in range(1, p) if len(set([x**i % p for i in range(1, p)])) == p-1][0]\n 3 k = 4\n 4 t = g**k % p\n 5 m = 6\n 6 import random\n 7 r = random.randint(1, p-1)\n 8 c1 = g**r % p\n 9 c2 = (t**r * m) % p\n 10 inv_k = p - 1 - k\n 11 inv_c1 = c1**inv_k % p\n 12 message = c2 * inv_c1 % p\n 13 print \"YOU ARE A CRYPTOSTAR!\" if message == m else \"ERROR\"\n\n YOU ARE A CRYPTOSTAR!\n\nBesides line #2 that involves an algorithm to find the generator \\`g\\` and line #10 that calculates the additive inverse of private key \\`k\\`, everything else is just modular multiplication and exponentiation.\n\nInterested in more details and line by line explanations? please read on.\n\n\n# Discrete logarithm trapdoor\n\nFirst thing first, lets pick a prime number:\n\n 1 p = 7\n\nFor the prime number above we need to find the generator \\`g\\` that defines a [cyclic group](https://en.wikipedia.org/wiki/Cyclic_group) which in theory is a little bit involved but in simple terms the generator is a specific number that returns unique values for each exponent between \\`1\\` and \\`p-1\\` where \\`p-1\\` is called the order of the cyclic group.\n\nLets take a few examples and see how it looks like: pick \\`2\\` as generator:\n\n print [2**i % p for i in range(1, p)]\n\n [2, 4, 1, 2, 4, 1]\n\nWe can easily see that returning values are not unique, lets pick \\`3\\` as generator:\n\n print [3**i % p for i in range(1, p)]\n\n [3, 2, 6, 4, 5, 1]\n\nBINGO! returning values are unique and we've found our generator.\n\nThe line below is just a brute force algorithm that finds multiple generators of order \\`p-1\\` but only takes the first one that is found.\n\n 2 g = [x for x in range(1, p) if len(set([x**i % p for i in range(1, p)])) == p-1][0]\n\nNow is time to pick a private key \\`k\\` between \\`1\\` and \\`p-1\\`, execute the trapdoor function and calculate \\`t\\` value:\n\n 3 k = 4\n 4 t = g**k % p\n\nThe line #4 is the secret sauce of ElGamal cryptography, the trapdoor function called [**the discrete logarithm**](https://en.wikipedia.org/wiki/Discrete_logarithm) which says that for given \\`g\\` and \\`t\\` values it is **infeasible** to calculate the private key \\`k\\` when working with very large numbers.\n\nThe \\`p, g and t\\` form the public key and will be used in encryption below, while \\`k\\` is kept secret.\n\n\n# Message encryption\n\n\\`m\\` is the message that we want to encrypt and \\`r\\` is a random number between \\`1\\` and \\`p-1\\`:\n\n 5 m = 6\n 6 import random\n 7 r = random.randint(1, p-1)\n 8 c1 = g**r % p\n 9 c2 = (t**r * m) % p\n\n\\`c1, c2\\` are the encrypted ciphers that will be used to decrypt the original message.\n\n\n# Message decryption\n\nTo decrypt the original message we need apply the following formula:\n\n\\`message = c2 / c1<sup>k</sup> mod p\\`\n\nThe problem is that division is not an operation defined for finite fields but multiplication is and we can re-write it using multiplication / exponentiation operations only:\n\n\\`message = c2 \\* c1<sup>inv</sup><sub>k</sub> mod p\\`\n\n\\`inv<sub>k</sub>\\` is called [additive inverse](https://en.wikipedia.org/wiki/Additive_inverse) of \\`k\\` over [finite field](https://en.wikipedia.org/wiki/Finite_field) 'p' where \\`k + inv<sub>k</sub> mod p = 0\\` is valid.\nWe can brute force and find it but there is a simpler way: if \\`k < p\\` (which it is) then \\`inv<sub>k</sub> = p - 1 - k\\`.\n\n 10 inv_k = p - 1 - k\n 11 inv_c1 = c1**inv_k % p\n 12 message = c2 * inv_c1 % p\n 13 print \"YOU ARE A CRYPTOSTAR!\" if message == m else \"ERROR\"\n\n YOU ARE A CRYPTOSTAR!\n\n\n# Intuition\n\nWhy this magic works the way it works?\n\n 1 message == (c2 * inv_c1) % p\n 2 message == (c2 * c1**(p-1-k)) % p\n 3 message == (t**r * m * (g**r)**(p-1-k)) % p\n 4 message == ((g**k)**r * m * (g**r)**(p-1-k)) % p\n 5 message == (g**(k*r) * m * (g**(r*(p-1-k)))) % p\n 6 message == (g**(k*r) * m * g**(r*(p-1)) * g**(-r*k)) % p\n\nLets do the math backwards:\n\n1. start with last decryption formula and substitute inverses \\`inv<sub>c1</sub>\\` and \\`inv<sub>k</sub>\\`\n2. substitute ciphers \\`c1\\` and \\`c2\\`\n3. substitute trapdoor \\`t\\`\n4. apply exponentiation power rule \\`(a<sup>b</sup>)<sup>c</sup> = a<sup>(b\\*c)</sup>\\`\n5. distribute the exponent \\`r\\`\n6. - \\`g\\*\\*(r\\*(p-1))\\` is 1 because of [Euler's theorem](https://en.wikipedia.org/wiki/Euler%2527s_theorem) and [Lagrange's theorem](https://en.wikipedia.org/wiki/Lagrange%2527s_theorem_(group_theory))\n - \\`g\\*\\*(k\\*r)\\` terms reduces each other\n\nCheck if the intuition is valid by substituting with numbers: generator \\`g\\` is 3, private key \\`k\\` is 4, random number \\`r\\` is 5 and message \\`m\\` is 6:\n\n print \"MAGIC\" if 6 == (3**(4*5) * 6 * 3**(5*(7-1)) * 3**(-5*4)) % 7 else \"ERROR\"\n\n MAGIC",
"json_metadata": "{\"tags\":[\"cryptography\",\"elgamal\",\"discrete\",\"logarithm\",\"eli5\"],\"links\":[\"https://en.wikipedia.org/wiki/ElGamal_encryption\",\"https://en.wikipedia.org/wiki/ElGamal_signature_scheme\",\"https://en.wikipedia.org/wiki/Cyclic_group\",\"https://en.wikipedia.org/wiki/Discrete_logarithm\",\"https://en.wikipedia.org/wiki/Additive_inverse\",\"https://en.wikipedia.org/wiki/Finite_field\",\"https://en.wikipedia.org/wiki/Euler%2527s_theorem\",\"https://en.wikipedia.org/wiki/Lagrange%2527s_theorem_(group_theory)\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "cryptography",
"permlink": "eli5-cryptography-elgamal",
"title": "ELI5: Cryptography - ElGamal"
}
],
"op_in_trx": 0,
"timestamp": "2019-03-27T13:27:09",
"trx_id": "c7450e9258272e819fb52141040f589b74abc18c",
"trx_in_block": 13,
"virtual_op": 0
}steffenixupvoted (100.00%) @icostan / eli5-cryptography-rsa2019/03/23 13:41:36
steffenixupvoted (100.00%) @icostan / eli5-cryptography-rsa
2019/03/23 13:41:36
| author | icostan |
| permlink | eli5-cryptography-rsa |
| voter | steffenix |
| weight | 10000 (100.00%) |
| Transaction Info | Block #31406442/Trx 8ed47132be8f40a869b012cb3d0f346f9a5a9a1f |
View Raw JSON Data
{
"block": 31406442,
"op": [
"vote",
{
"author": "icostan",
"permlink": "eli5-cryptography-rsa",
"voter": "steffenix",
"weight": 10000
}
],
"op_in_trx": 0,
"timestamp": "2019-03-23T13:41:36",
"trx_id": "8ed47132be8f40a869b012cb3d0f346f9a5a9a1f",
"trx_in_block": 21,
"virtual_op": 0
}taijosupvoted (100.00%) @icostan / eli5-cryptography-rsa2019/03/23 13:38:57
taijosupvoted (100.00%) @icostan / eli5-cryptography-rsa
2019/03/23 13:38:57
| author | icostan |
| permlink | eli5-cryptography-rsa |
| voter | taijos |
| weight | 10000 (100.00%) |
| Transaction Info | Block #31406389/Trx 6f1b68d77fb68d8ad7f2342ba79d8ed887a6cbd9 |
View Raw JSON Data
{
"block": 31406389,
"op": [
"vote",
{
"author": "icostan",
"permlink": "eli5-cryptography-rsa",
"voter": "taijos",
"weight": 10000
}
],
"op_in_trx": 0,
"timestamp": "2019-03-23T13:38:57",
"trx_id": "6f1b68d77fb68d8ad7f2342ba79d8ed887a6cbd9",
"trx_in_block": 0,
"virtual_op": 0
}icostanpublished a new post: eli5-cryptography-rsa2019/03/23 13:30:15
icostanpublished a new post: eli5-cryptography-rsa
2019/03/23 13:30:15
| author | icostan |
| body | # Overview "If you can't explain it simply, you don't understand it well enough" - Einstein --- [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) (Rivest-Shamir-Adleman) needs no introduction, it is well known and most used public-key cryptosystem that governs our digital lives. Here is my take, a simple implementation in 10 lines of Ruby code that is neither the best implementation nor the most efficient one but is enough for the purpose of this article. 1 p = 7 2 q = 11 3 n = p * q 4 phi = (p-1) * (q-1) 5 gcd = ->(a, b) { while(b != 0) do r, a = a % b, b; b = r end; a } 6 e = (2..phi).find{|i| gcd.call(i, phi) == 1 } 7 d = (2..phi).find{|i| (i * e) % phi == 1 } 8 m = 6 9 c = m**e % n 10 message = c**d % n 11 "Decrypted message: #{message}" if m == message Except lines #5 that involves an algorithm and a while loop, everything else is mid-school math and \`\*\*\` is the exponentiation operator. The curious minds please read simple explanations below. # Integer factorization trapdoor The very first thing to do is to choose 2 prime numbers, \`p\` and \`q\`: 1 p = 7 2 q = 11 Next, let's multiply the two numbers: 3 n = p * q Now it's time to define our first function \`phi\`: 4 phi = (p-1) * (q-1) Which is [Euler's totient function](<https://en.wikipedia.org/wiki/Euler%27s_totient_function>) defined as number of integers less than \`n\` that are [coprime](https://en.wikipedia.org/wiki/Coprime_integers) with \`n\` and has two interesting properties: - the function is multiplicative and \`phi(a\*b) = phi(a) \* phi(b)\` - if \`n\` is a prime number then \`phi(n) = n - 1\` And finally we have the [cryptographic trapdoor](https://en.wikipedia.org/wiki/Trapdoor_function) which is the most important primitive to understand. Trapdoors are based on asymmetric computation that is easy to do in one direction but it is very difficult to calculate in the opposite direction. In our case, if one (an attacker) does not know the initial \`p\` and \`q\` prime numbers it will be very hard to calculate the \`phi\` because [integer factorization](https://en.wikipedia.org/wiki/Integer_factorization) of \`n\` is known to be infeasible to calculate for very large numbers. # Message encryption Now it's time to define our first algorithm, \`gcd\` which is the [greatest common divisor](<https://en.wikipedia.org/wiki/Greatest_common_divisor>) and is defined as the largest positive integer that divides both \`a\` and \`b\`. If single-liner GCD looks scary then here is the formatted version of the [Euclid's algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm). def gcd(a, b) while(b != 0) do r = a % b a = b b = r end a end The \`e\` key below is the encryption key and is defined as the smallest value for which \`gcd(e, phi) == 1\` is true. To keep things simple we will just brute-force and find \`e\` but keep in mind that this will be very inefficient for large numbers. 5 gcd = ->(a, b) { while(b != 0) do r, a = a % b, b; b = r end; a } (gcd) 6 e = (2..phi).find{|i| gcd.call(i, phi) == 1} Message encryption is modulo exponentiation of the message \`m\` and the encryption key \`e\`. 7 m = 6 8 c = m**e % n # Message decryption The \`d\` key below is the decryption key and is defined as [multiplicative inverse](https://en.wikipedia.org/wiki/Multiplicative_inverse) of \`e\` over [finite field](https://en.wikipedia.org/wiki/Finite_field) \`phi\`. Simply put \`e \* d mod phi = 1\`. Again we will just brute-force and calculate the inverse but there are better algorithms to do this, like [Extended Euclidean algorithm](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm). 9 d = (2..phi).find{|i| (e * i) % phi == 1} Message decryption is another modulo exponentiation using the encrypted cipher \`c\` and decryption key \`d\`: 10 message = c**d % n BINGO! You can try it yourself but I can bet that \`m = message = 6\` # Intuition At first sight it looks like magic right? but if you reason about it, it's very easy. Starting backwards, with the decryption/encryption formulas: 1 m = c^d mod n 2 c = m^e mod n Let's substitute #2 in #1: m = (m^e)^d mod n Exponentials Power Rule says that \`(a<sup>b</sup>)<sup>c</sup> == a<sup>(b\*c)</sup>\` and we also know that \`d\` is the multiplicative inverse of \`e\`, guess what is the value of the resulting exponent? :) m = m^(e*d mod phi) mod p If the intuition is valid then the following expression stands true, where 7 is \`e\` and 43 is \`d\` in our little example: 'YOU ARE A CRYPTOSTAR!!!' if 6 == 6**(7 * 43 % 60) % 77 |
| json metadata | {"tags":["cryptography","rsa","primes","factorization","eli5"],"links":["https://en.wikipedia.org/wiki/RSA_(cryptosystem)","https://en.wikipedia.org/wiki/Euler's_totient_function","https://en.wikipedia.org/wiki/Coprime_integers","https://en.wikipedia.org/wiki/Trapdoor_function","https://en.wikipedia.org/wiki/Integer_factorization","https://en.wikipedia.org/wiki/Greatest_common_divisor","https://en.wikipedia.org/wiki/Euclidean_algorithm","https://en.wikipedia.org/wiki/Multiplicative_inverse","https://en.wikipedia.org/wiki/Finite_field","https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | cryptography |
| permlink | eli5-cryptography-rsa |
| title | ELI5 Cryptography: RSA |
| Transaction Info | Block #31406215/Trx 26d641da6f108d903477e97ca55524a006fc89cd |
View Raw JSON Data
{
"block": 31406215,
"op": [
"comment",
{
"author": "icostan",
"body": "# Overview\n\n \"If you can't explain it simply, you don't understand it well enough\" - Einstein\n---\n\n[RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) (Rivest-Shamir-Adleman) needs no introduction, it is well known and most used public-key cryptosystem that governs our digital lives.\n\nHere is my take, a simple implementation in 10 lines of Ruby code that is neither the best implementation nor the most efficient one but is enough for the purpose of this article.\n\n 1 p = 7\n 2 q = 11\n 3 n = p * q\n 4 phi = (p-1) * (q-1)\n 5 gcd = ->(a, b) { while(b != 0) do r, a = a % b, b; b = r end; a }\n 6 e = (2..phi).find{|i| gcd.call(i, phi) == 1 }\n 7 d = (2..phi).find{|i| (i * e) % phi == 1 }\n 8 m = 6\n 9 c = m**e % n\n 10 message = c**d % n\n 11 \"Decrypted message: #{message}\" if m == message\n\nExcept lines #5 that involves an algorithm and a while loop, everything else is mid-school math and \\`\\*\\*\\` is the exponentiation operator.\n\nThe curious minds please read simple explanations below.\n\n\n# Integer factorization trapdoor\n\nThe very first thing to do is to choose 2 prime numbers, \\`p\\` and \\`q\\`:\n\n 1 p = 7\n\n 2 q = 11\n\nNext, let's multiply the two numbers:\n\n 3 n = p * q\n\nNow it's time to define our first function \\`phi\\`:\n\n 4 phi = (p-1) * (q-1)\n\nWhich is [Euler's totient function](<https://en.wikipedia.org/wiki/Euler%27s_totient_function>) defined as number of integers less than \\`n\\` that are [coprime](https://en.wikipedia.org/wiki/Coprime_integers) with \\`n\\` and has two interesting properties:\n\n- the function is multiplicative and \\`phi(a\\*b) = phi(a) \\* phi(b)\\`\n- if \\`n\\` is a prime number then \\`phi(n) = n - 1\\`\n\nAnd finally we have the [cryptographic trapdoor](https://en.wikipedia.org/wiki/Trapdoor_function) which is the most important primitive to understand. Trapdoors are based on asymmetric computation that is easy to do in one direction but it is very difficult to calculate in the opposite direction.\n\nIn our case, if one (an attacker) does not know the initial \\`p\\` and \\`q\\` prime numbers it will be very hard to calculate the \\`phi\\` because [integer factorization](https://en.wikipedia.org/wiki/Integer_factorization) of \\`n\\` is known to be infeasible to calculate for very large numbers.\n\n\n# Message encryption\n\nNow it's time to define our first algorithm, \\`gcd\\` which is the [greatest common divisor](<https://en.wikipedia.org/wiki/Greatest_common_divisor>) and is defined as the largest positive integer that divides both \\`a\\` and \\`b\\`.\n\nIf single-liner GCD looks scary then here is the formatted version of the [Euclid's algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).\n\n def gcd(a, b)\n while(b != 0) do\n r = a % b\n a = b\n b = r\n end\n a\n end\n\nThe \\`e\\` key below is the encryption key and is defined as the smallest value for which \\`gcd(e, phi) == 1\\` is true.\nTo keep things simple we will just brute-force and find \\`e\\` but keep in mind that this will be very inefficient for large numbers.\n\n 5 gcd = ->(a, b) { while(b != 0) do r, a = a % b, b; b = r end; a } (gcd)\n 6 e = (2..phi).find{|i| gcd.call(i, phi) == 1}\n\nMessage encryption is modulo exponentiation of the message \\`m\\` and the encryption key \\`e\\`.\n\n 7 m = 6\n 8 c = m**e % n\n\n\n# Message decryption\n\nThe \\`d\\` key below is the decryption key and is defined as [multiplicative inverse](https://en.wikipedia.org/wiki/Multiplicative_inverse) of \\`e\\` over [finite field](https://en.wikipedia.org/wiki/Finite_field) \\`phi\\`. Simply put \\`e \\* d mod phi = 1\\`.\n\nAgain we will just brute-force and calculate the inverse but there are better algorithms to do this, like [Extended Euclidean algorithm](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm).\n\n 9 d = (2..phi).find{|i| (e * i) % phi == 1}\n\nMessage decryption is another modulo exponentiation using the encrypted cipher \\`c\\` and decryption key \\`d\\`:\n\n 10 message = c**d % n\n\nBINGO! You can try it yourself but I can bet that \\`m = message = 6\\`\n\n\n# Intuition\n\nAt first sight it looks like magic right? but if you reason about it, it's very easy.\n\nStarting backwards, with the decryption/encryption formulas:\n\n 1 m = c^d mod n\n 2 c = m^e mod n\n\nLet's substitute #2 in #1:\n\n m = (m^e)^d mod n\n\nExponentials Power Rule says that \\`(a<sup>b</sup>)<sup>c</sup> == a<sup>(b\\*c)</sup>\\` and we also know that \\`d\\` is the multiplicative inverse of \\`e\\`, guess what is the value of the resulting exponent? :)\n\n m = m^(e*d mod phi) mod p\n\nIf the intuition is valid then the following expression stands true, where 7 is \\`e\\` and 43 is \\`d\\` in our little example:\n\n 'YOU ARE A CRYPTOSTAR!!!' if 6 == 6**(7 * 43 % 60) % 77",
"json_metadata": "{\"tags\":[\"cryptography\",\"rsa\",\"primes\",\"factorization\",\"eli5\"],\"links\":[\"https://en.wikipedia.org/wiki/RSA_(cryptosystem)\",\"https://en.wikipedia.org/wiki/Euler's_totient_function\",\"https://en.wikipedia.org/wiki/Coprime_integers\",\"https://en.wikipedia.org/wiki/Trapdoor_function\",\"https://en.wikipedia.org/wiki/Integer_factorization\",\"https://en.wikipedia.org/wiki/Greatest_common_divisor\",\"https://en.wikipedia.org/wiki/Euclidean_algorithm\",\"https://en.wikipedia.org/wiki/Multiplicative_inverse\",\"https://en.wikipedia.org/wiki/Finite_field\",\"https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "cryptography",
"permlink": "eli5-cryptography-rsa",
"title": "ELI5 Cryptography: RSA"
}
],
"op_in_trx": 0,
"timestamp": "2019-03-23T13:30:15",
"trx_id": "26d641da6f108d903477e97ca55524a006fc89cd",
"trx_in_block": 13,
"virtual_op": 0
}icostanfollowed @luigi11112019/02/07 14:03:27
icostanfollowed @luigi1111
2019/02/07 14:03:27
| id | follow |
| json | ["follow",{"follower":"icostan","following":"luigi1111","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #30140588/Trx 68e0b372067c2838d7aa63f432a65d15f2c97285 |
View Raw JSON Data
{
"block": 30140588,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"luigi1111\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2019-02-07T14:03:27",
"trx_id": "68e0b372067c2838d7aa63f432a65d15f2c97285",
"trx_in_block": 5,
"virtual_op": 0
}2019/02/07 02:56:48
2019/02/07 02:56:48
| delegatee | icostan |
| delegator | steem |
| vesting shares | 29053.803726 VESTS |
| Transaction Info | Block #30127263/Trx 6851f8d148247f481b212d07799006a3627197f8 |
View Raw JSON Data
{
"block": 30127263,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "29053.803726 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2019-02-07T02:56:48",
"trx_id": "6851f8d148247f481b212d07799006a3627197f8",
"trx_in_block": 32,
"virtual_op": 0
}icostanpublished a new post: idiomatic-ruby-library-for-bitmex-api2019/02/02 13:03:27
icostanpublished a new post: idiomatic-ruby-library-for-bitmex-api
2019/02/02 13:03:27
| author | icostan |
| body | # Bitmex-api-ruby Fully featured, idiomatic Ruby library for BitMEX API. Support for both REST and Websocket APIs as described in [API Overview](https://www.bitmex.com/app/apiOverview). ## Installation ```shell gem install bitmex-api ``` ## Usage Listen for live trades in 3 lines of code: ```ruby # Importing library... 2.5.3 :001 > require 'bitmex-api' => true # Create client... 2.5.3 :002 > client = Bitmex::Client.new => #<Bitmex::Client:0x00007fae7a569598 @host="www.bitmex.com", @api_key=nil, @api_secret=nil> # Spit out live trades as they happen... 2.5.3 :003 > client.trades.all symbol: 'XBTUSD' do |trade| puts "#{trade.side} #{trade.homeNotional} #{trade.symbol} @ #{trade.price}" end 2.5.3 :004 > 2.5.3 :005?> ==> {"info":"Welcome to the BitMEX Realtime API.","version":"2019-01-31T23:25:34.000Z","timestamp":"2019-02-02T12:35:05.892Z","docs":"https://www.bitmex.com/app/wsAPI","limit":{"remaining":37}} ==> {"success":true,"subscribe":"trade:XBTUSD","request":{"op":"subscribe","args":["trade:XBTUSD"]}} Buy 0.2924442 XBTUSD @ 3440 Sell 0.0305277 XBTUSD @ 3439.5 Buy 0.2907 XBTUSD @ 3440 Sell 0.18810878 XBTUSD @ 3439.5 Sell 0.14537 XBTUSD @ 3439.5 Buy 0.17442 XBTUSD @ 3440 Buy 0.05814 XBTUSD @ 3440 Sell 0.014537 XBTUSD @ 3439.5 ``` Or fetch trade history: ```ruby # get first 10 trades of the year 2.5.3 :006 > trades = client.trades.all symbol: 'XBTUSD', startTime: '2019-01-01', count: 10 => [...] 2.5.3 :007 > trades.size => 10 # the very first trade in 2019 2.5.3 :008 > trades.first => #<Bitmex::Mash foreignNotional=10 grossValue=270780 homeNotional=0.0027078 price=3693 side="Sell" size=10 symbol="XBTUSD" tickDirection="ZeroMinusTick" timestamp="2019-01-01T00:00:03.904Z" trdMatchID="2bd201ae-3b79-0908-293e-d9bd1cc489f2"> ``` This post is just a teaser, if you want to find out more info please see [source code](https://github.com/icostan/bitmex-api-ruby) and [documentation](https://www.rubydoc.info/gems/bitmex-api). Enjoy futures trading! |
| json metadata | {"tags":["bitmex","ruby","library","json","websocket"],"links":["https://www.bitmex.com/app/apiOverview","https://github.com/icostan/bitmex-api-ruby","https://www.rubydoc.info/gems/bitmex-api"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | bitmex |
| permlink | idiomatic-ruby-library-for-bitmex-api |
| title | Idiomatic Ruby library for BitMEX API |
| Transaction Info | Block #29995542/Trx 022c57bb018022bea1920181579a795b159aee8d |
View Raw JSON Data
{
"block": 29995542,
"op": [
"comment",
{
"author": "icostan",
"body": "# Bitmex-api-ruby\n\nFully featured, idiomatic Ruby library for BitMEX API. Support for both REST and Websocket APIs as described in [API Overview](https://www.bitmex.com/app/apiOverview).\n\n## Installation\n\n```shell\ngem install bitmex-api\n```\n\n## Usage\n\nListen for live trades in 3 lines of code:\n\n```ruby\n# Importing library...\n2.5.3 :001 > require 'bitmex-api'\n => true\n\n# Create client...\n2.5.3 :002 > client = Bitmex::Client.new\n => #<Bitmex::Client:0x00007fae7a569598 @host=\"www.bitmex.com\", @api_key=nil, @api_secret=nil>\n\n# Spit out live trades as they happen...\n2.5.3 :003 > client.trades.all symbol: 'XBTUSD' do |trade|\n puts \"#{trade.side} #{trade.homeNotional} #{trade.symbol} @ #{trade.price}\"\nend\n2.5.3 :004 >\n2.5.3 :005?>\n==> {\"info\":\"Welcome to the BitMEX Realtime API.\",\"version\":\"2019-01-31T23:25:34.000Z\",\"timestamp\":\"2019-02-02T12:35:05.892Z\",\"docs\":\"https://www.bitmex.com/app/wsAPI\",\"limit\":{\"remaining\":37}}\n==> {\"success\":true,\"subscribe\":\"trade:XBTUSD\",\"request\":{\"op\":\"subscribe\",\"args\":[\"trade:XBTUSD\"]}}\nBuy 0.2924442 XBTUSD @ 3440\nSell 0.0305277 XBTUSD @ 3439.5\nBuy 0.2907 XBTUSD @ 3440\nSell 0.18810878 XBTUSD @ 3439.5\nSell 0.14537 XBTUSD @ 3439.5\nBuy 0.17442 XBTUSD @ 3440\nBuy 0.05814 XBTUSD @ 3440\nSell 0.014537 XBTUSD @ 3439.5\n```\n\nOr fetch trade history:\n\n```ruby\n# get first 10 trades of the year\n2.5.3 :006 > trades = client.trades.all symbol: 'XBTUSD', startTime: '2019-01-01', count: 10\n => [...]\n\n2.5.3 :007 > trades.size\n => 10\n\n# the very first trade in 2019\n2.5.3 :008 > trades.first\n => #<Bitmex::Mash foreignNotional=10 grossValue=270780 homeNotional=0.0027078 price=3693 side=\"Sell\" size=10 symbol=\"XBTUSD\" tickDirection=\"ZeroMinusTick\" timestamp=\"2019-01-01T00:00:03.904Z\" trdMatchID=\"2bd201ae-3b79-0908-293e-d9bd1cc489f2\">\n```\n\nThis post is just a teaser, if you want to find out more info please see [source code](https://github.com/icostan/bitmex-api-ruby) and [documentation](https://www.rubydoc.info/gems/bitmex-api).\n\nEnjoy futures trading!",
"json_metadata": "{\"tags\":[\"bitmex\",\"ruby\",\"library\",\"json\",\"websocket\"],\"links\":[\"https://www.bitmex.com/app/apiOverview\",\"https://github.com/icostan/bitmex-api-ruby\",\"https://www.rubydoc.info/gems/bitmex-api\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "bitmex",
"permlink": "idiomatic-ruby-library-for-bitmex-api",
"title": "Idiomatic Ruby library for BitMEX API"
}
],
"op_in_trx": 0,
"timestamp": "2019-02-02T13:03:27",
"trx_id": "022c57bb018022bea1920181579a795b159aee8d",
"trx_in_block": 7,
"virtual_op": 0
}2019/01/18 09:22:18
2019/01/18 09:22:18
| author | partiko |
| body | Thank you so much for sharing this amazing post with us! Have you heard about Partiko? It’s a really convenient mobile app for Steem! With Partiko, you can easily see what’s going on in the Steem community, make posts and comments (no beneficiary cut forever!), and always stayed connected with your followers via push notification! Partiko also rewards you with Partiko Points (3000 Partiko Point bonus when you first use it!), and Partiko Points can be converted into Steem tokens. You can earn Partiko Points easily by making posts and comments using Partiko. We also noticed that your Steem Power is low. We will be very happy to delegate 15 Steem Power to you once you have made a post using Partiko! With more Steem Power, you can make more posts and comments, and earn more rewards! If that all sounds interesting, you can: - Download Partiko Android at [Google Play](http://bit.ly/2SRFIta) - Or Download Partiko iOS on the [App Store](https://apple.co/2PcXkSd) Thank you so much for reading this message! |
| json metadata | {"app":"partiko"} |
| parent author | icostan |
| parent permlink | release-cryptos-ruby-project |
| permlink | partiko-re-icostan-release-cryptos-ruby-project-20190118t092218331z |
| title | |
| Transaction Info | Block #29559550/Trx 9c5a859a044787eb870467f025b509c5daa84364 |
View Raw JSON Data
{
"block": 29559550,
"op": [
"comment",
{
"author": "partiko",
"body": "Thank you so much for sharing this amazing post with us!\n\nHave you heard about Partiko? It’s a really convenient mobile app for Steem! With Partiko, you can easily see what’s going on in the Steem community, make posts and comments (no beneficiary cut forever!), and always stayed connected with your followers via push notification!\n\nPartiko also rewards you with Partiko Points (3000 Partiko Point bonus when you first use it!), and Partiko Points can be converted into Steem tokens. You can earn Partiko Points easily by making posts and comments using Partiko.\n\nWe also noticed that your Steem Power is low. We will be very happy to delegate 15 Steem Power to you once you have made a post using Partiko! With more Steem Power, you can make more posts and comments, and earn more rewards!\n\nIf that all sounds interesting, you can: \n\n- Download Partiko Android at [Google Play](http://bit.ly/2SRFIta)\n- Or Download Partiko iOS on the [App Store](https://apple.co/2PcXkSd)\n\nThank you so much for reading this message!",
"json_metadata": "{\"app\":\"partiko\"}",
"parent_author": "icostan",
"parent_permlink": "release-cryptos-ruby-project",
"permlink": "partiko-re-icostan-release-cryptos-ruby-project-20190118t092218331z",
"title": ""
}
],
"op_in_trx": 0,
"timestamp": "2019-01-18T09:22:18",
"trx_id": "9c5a859a044787eb870467f025b509c5daa84364",
"trx_in_block": 14,
"virtual_op": 0
}icostanpublished a new post: release-cryptos-ruby-project2018/12/13 07:25:27
icostanpublished a new post: release-cryptos-ruby-project
2018/12/13 07:25:27
| author | icostan |
| body | I just want to announce the very first release [v0.0.3] of Cryptos-ruby project, a simple and very easy to use Ruby API to manipulate multiple crypto coins. For more information please check [Github project page](https://github.com/icostan/cryptos-ruby). ## Features * Generate private/public keys * Generate Bitcoin/Litecoin addresses (more to come) * Create Bitcoin/Litecoin transactions * Execute atomic swaps between Bitcoin and Litecoin ## Installation ```shell gem install cryptos ``` ## Usage ```ruby # Importing library... 2.5.1 :001 > require 'cryptos' # Generating private key... 2.5.1 :003 > private_key = Cryptos::PrivateKey.generate => #<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337> # Generating public key... 2.5.1 :004 > public_key = Cryptos::PublicKey.new private_key => #<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541> # Generating Bitcoin address for testnet 2.5.1 :005 > address = Cryptos::Bitcoin::Address.new public_key => #<Cryptos::Bitcoin::Address:0x00007fc9d18a29b8 @public_key=#<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>, @testnet=true> 2.5.1 :006 > address.to_s => "n37t517bJymxg3YftzqyVTAnjg4wKb3Tth" # Generating Litecoin address for mainnet 2.5.1 :007 > address = Cryptos::Litecoin::Address.new public_key, testnet: false => #<Cryptos::Litecoin::Address:0x00007fc9d119a1e8 @public_key=#<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>, @testnet=false> 2.5.1 :008 > address.to_s => "Lgpt3ALSacam9jmDMZrtwZ2E5tqWVYzEkH" ``` ## Todos * Work in progress: Zcash and Ethereum support * Add more and more coins, cool crypto tech |
| json metadata | {"tags":["crypto","bitcoin","litecoin","transaction","atomicswaps"],"links":["https://github.com/icostan/cryptos-ruby"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | crypto |
| permlink | release-cryptos-ruby-project |
| title | Introducing Cryptos-ruby: The easiest way to craft your own transactions |
| Transaction Info | Block #28521203/Trx 0d6de8f50b2bf982713df05f53f711cbd0489cdf |
View Raw JSON Data
{
"block": 28521203,
"op": [
"comment",
{
"author": "icostan",
"body": "I just want to announce the very first release [v0.0.3] of Cryptos-ruby project, a simple and very easy to use Ruby API to manipulate multiple crypto coins.\n\nFor more information please check [Github project page](https://github.com/icostan/cryptos-ruby).\n\n## Features\n * Generate private/public keys\n * Generate Bitcoin/Litecoin addresses (more to come)\n * Create Bitcoin/Litecoin transactions\n * Execute atomic swaps between Bitcoin and Litecoin\n\n## Installation\n```shell\ngem install cryptos\n```\n## Usage\n\n```ruby\n# Importing library...\n2.5.1 :001 > require 'cryptos'\n\n# Generating private key...\n2.5.1 :003 > private_key = Cryptos::PrivateKey.generate\n => #<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>\n\n# Generating public key...\n2.5.1 :004 > public_key = Cryptos::PublicKey.new private_key\n => #<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>\n\n# Generating Bitcoin address for testnet\n2.5.1 :005 > address = Cryptos::Bitcoin::Address.new public_key\n => #<Cryptos::Bitcoin::Address:0x00007fc9d18a29b8 @public_key=#<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>, @testnet=true>\n2.5.1 :006 > address.to_s\n => \"n37t517bJymxg3YftzqyVTAnjg4wKb3Tth\"\n\n# Generating Litecoin address for mainnet\n2.5.1 :007 > address = Cryptos::Litecoin::Address.new public_key, testnet: false\n => #<Cryptos::Litecoin::Address:0x00007fc9d119a1e8 @public_key=#<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>, @testnet=false>\n2.5.1 :008 > address.to_s\n => \"Lgpt3ALSacam9jmDMZrtwZ2E5tqWVYzEkH\"\n```\n\n## Todos\n * Work in progress: Zcash and Ethereum support\n * Add more and more coins, cool crypto tech",
"json_metadata": "{\"tags\":[\"crypto\",\"bitcoin\",\"litecoin\",\"transaction\",\"atomicswaps\"],\"links\":[\"https://github.com/icostan/cryptos-ruby\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "crypto",
"permlink": "release-cryptos-ruby-project",
"title": "Introducing Cryptos-ruby: The easiest way to craft your own transactions"
}
],
"op_in_trx": 0,
"timestamp": "2018-12-13T07:25:27",
"trx_id": "0d6de8f50b2bf982713df05f53f711cbd0489cdf",
"trx_in_block": 2,
"virtual_op": 0
}2018/12/11 09:26:51
2018/12/11 09:26:51
| amount | 0.001 SBD |
| from | allaz |
| memo | Promote your post. Your post will be min. 10 resteemed with over 13000 followers and min. 25 Upvote Different account (5000 STEEM POWER). Your post will be more popular and you will find new friends. Send 0.5 SBD or STEEM to @allaz (post URL as memo ) Service Active. |
| to | icostan |
| Transaction Info | Block #28466082/Trx 1e16bf0a26371fd2ef5dbbae4fbe1b67a6ae1999 |
View Raw JSON Data
{
"block": 28466082,
"op": [
"transfer",
{
"amount": "0.001 SBD",
"from": "allaz",
"memo": "Promote your post. Your post will be min. 10 resteemed with over 13000 followers and min. 25 Upvote Different account (5000 STEEM POWER). Your post will be more popular and you will find new friends. Send 0.5 SBD or STEEM to @allaz (post URL as memo ) Service Active.",
"to": "icostan"
}
],
"op_in_trx": 0,
"timestamp": "2018-12-11T09:26:51",
"trx_id": "1e16bf0a26371fd2ef5dbbae4fbe1b67a6ae1999",
"trx_in_block": 0,
"virtual_op": 0
}icostanpublished a new post: release-cryptos-ruby-project2018/12/11 09:25:27
icostanpublished a new post: release-cryptos-ruby-project
2018/12/11 09:25:27
| author | icostan |
| body | @@ -1,37 +1,4 @@ -# Release: Cryptos-ruby project%0A%0A I ju |
| json metadata | {"tags":["crypto","bitcoin","litecoin","transaction","atomicswaps"],"links":["https://github.com/icostan/cryptos-ruby"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | crypto |
| permlink | release-cryptos-ruby-project |
| title | Release: Cryptos-ruby project |
| Transaction Info | Block #28466054/Trx 50e311b5989627231103dc0e6858bbf544f88a41 |
View Raw JSON Data
{
"block": 28466054,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -1,37 +1,4 @@\n-# Release: Cryptos-ruby project%0A%0A\n I ju\n",
"json_metadata": "{\"tags\":[\"crypto\",\"bitcoin\",\"litecoin\",\"transaction\",\"atomicswaps\"],\"links\":[\"https://github.com/icostan/cryptos-ruby\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "crypto",
"permlink": "release-cryptos-ruby-project",
"title": "Release: Cryptos-ruby project"
}
],
"op_in_trx": 0,
"timestamp": "2018-12-11T09:25:27",
"trx_id": "50e311b5989627231103dc0e6858bbf544f88a41",
"trx_in_block": 2,
"virtual_op": 0
}icostanpublished a new post: release-cryptos-ruby-project2018/12/11 09:24:36
icostanpublished a new post: release-cryptos-ruby-project
2018/12/11 09:24:36
| author | icostan |
| body | # Release: Cryptos-ruby project I just want to announce the very first release [v0.0.3] of Cryptos-ruby project, a simple and very easy to use Ruby API to manipulate multiple crypto coins. For more information please check [Github project page](https://github.com/icostan/cryptos-ruby). ## Features * Generate private/public keys * Generate Bitcoin/Litecoin addresses (more to come) * Create Bitcoin/Litecoin transactions * Execute atomic swaps between Bitcoin and Litecoin ## Installation ```shell gem install cryptos ``` ## Usage ```ruby # Importing library... 2.5.1 :001 > require 'cryptos' # Generating private key... 2.5.1 :003 > private_key = Cryptos::PrivateKey.generate => #<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337> # Generating public key... 2.5.1 :004 > public_key = Cryptos::PublicKey.new private_key => #<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541> # Generating Bitcoin address for testnet 2.5.1 :005 > address = Cryptos::Bitcoin::Address.new public_key => #<Cryptos::Bitcoin::Address:0x00007fc9d18a29b8 @public_key=#<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>, @testnet=true> 2.5.1 :006 > address.to_s => "n37t517bJymxg3YftzqyVTAnjg4wKb3Tth" # Generating Litecoin address for mainnet 2.5.1 :007 > address = Cryptos::Litecoin::Address.new public_key, testnet: false => #<Cryptos::Litecoin::Address:0x00007fc9d119a1e8 @public_key=#<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>, @testnet=false> 2.5.1 :008 > address.to_s => "Lgpt3ALSacam9jmDMZrtwZ2E5tqWVYzEkH" ``` ## Todos * Work in progress: Zcash and Ethereum support * Add more and more coins, cool crypto tech |
| json metadata | {"tags":["crypto","bitcoin","litecoin","transaction","atomicswaps"],"links":["https://github.com/icostan/cryptos-ruby"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | crypto |
| permlink | release-cryptos-ruby-project |
| title | Release: Cryptos-ruby project |
| Transaction Info | Block #28466037/Trx 241d8dae108f73798bfd4100c7d8826847618d42 |
View Raw JSON Data
{
"block": 28466037,
"op": [
"comment",
{
"author": "icostan",
"body": "# Release: Cryptos-ruby project\n\nI just want to announce the very first release [v0.0.3] of Cryptos-ruby project, a simple and very easy to use Ruby API to manipulate multiple crypto coins.\n\nFor more information please check [Github project page](https://github.com/icostan/cryptos-ruby).\n\n## Features\n * Generate private/public keys\n * Generate Bitcoin/Litecoin addresses (more to come)\n * Create Bitcoin/Litecoin transactions\n * Execute atomic swaps between Bitcoin and Litecoin\n\n## Installation\n```shell\ngem install cryptos\n```\n## Usage\n\n```ruby\n# Importing library...\n2.5.1 :001 > require 'cryptos'\n\n# Generating private key...\n2.5.1 :003 > private_key = Cryptos::PrivateKey.generate\n => #<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>\n\n# Generating public key...\n2.5.1 :004 > public_key = Cryptos::PublicKey.new private_key\n => #<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>\n\n# Generating Bitcoin address for testnet\n2.5.1 :005 > address = Cryptos::Bitcoin::Address.new public_key\n => #<Cryptos::Bitcoin::Address:0x00007fc9d18a29b8 @public_key=#<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>, @testnet=true>\n2.5.1 :006 > address.to_s\n => \"n37t517bJymxg3YftzqyVTAnjg4wKb3Tth\"\n\n# Generating Litecoin address for mainnet\n2.5.1 :007 > address = Cryptos::Litecoin::Address.new public_key, testnet: false\n => #<Cryptos::Litecoin::Address:0x00007fc9d119a1e8 @public_key=#<Cryptos::PublicKey:0x00007fc9d122fc48 @private_key=#<Cryptos::PrivateKey:0x00007fc9d123e2e8 @value=47930083789607287790662857866073624449854924554643360243140359905082181414216, @order=115792089237316195423570985008687907852837564279074904382605163141518161494337>, @x=37935518911551901189910488779135983333966395037400135768523765072809885233888, @y=60841756395196742058661917858407687798753194961782162321894682162865330386541>, @testnet=false>\n2.5.1 :008 > address.to_s\n => \"Lgpt3ALSacam9jmDMZrtwZ2E5tqWVYzEkH\"\n```\n\n## Todos\n * Work in progress: Zcash and Ethereum support\n * Add more and more coins, cool crypto tech",
"json_metadata": "{\"tags\":[\"crypto\",\"bitcoin\",\"litecoin\",\"transaction\",\"atomicswaps\"],\"links\":[\"https://github.com/icostan/cryptos-ruby\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "crypto",
"permlink": "release-cryptos-ruby-project",
"title": "Release: Cryptos-ruby project"
}
],
"op_in_trx": 0,
"timestamp": "2018-12-11T09:24:36",
"trx_id": "241d8dae108f73798bfd4100c7d8826847618d42",
"trx_in_block": 11,
"virtual_op": 0
}mrbean1upvoted (100.00%) @icostan / the-hard-way-bitcoin-transactions2018/11/11 12:47:57
mrbean1upvoted (100.00%) @icostan / the-hard-way-bitcoin-transactions
2018/11/11 12:47:57
| author | icostan |
| permlink | the-hard-way-bitcoin-transactions |
| voter | mrbean1 |
| weight | 10000 (100.00%) |
| Transaction Info | Block #27606565/Trx 44b02e6526ea83b83e8ae841415827277e2b0318 |
View Raw JSON Data
{
"block": 27606565,
"op": [
"vote",
{
"author": "icostan",
"permlink": "the-hard-way-bitcoin-transactions",
"voter": "mrbean1",
"weight": 10000
}
],
"op_in_trx": 0,
"timestamp": "2018-11-11T12:47:57",
"trx_id": "44b02e6526ea83b83e8ae841415827277e2b0318",
"trx_in_block": 33,
"virtual_op": 0
}icostanpublished a new post: the-hard-way-bitcoin-transactions2018/11/11 12:40:57
icostanpublished a new post: the-hard-way-bitcoin-transactions
2018/11/11 12:40:57
| author | icostan |
| body | # The hard way - Bitcoin: Transaction This is Part 2 of 'The hard way - Bitcoin' series and I will start with 'the easy way' section first because even this gets a bit complex, then will continue with the hard stuff, crafting a Bitcoin transaction from scratch using basic math and cryptography. ## A. The easy way ### Create private key, public key and address We are going to generate private key, public key and Bitcoin testnet address to be used in this article. ```shell shell> bx seed # generate seed 27634686aa8838acaa68e27aea6c072534394ce411cb7d75 shell> echo 27634686aa8838acaa68e27aea6c072534394ce411cb7d75 | bx ec-new # generate private key 79020296790075fc8e36835e045c513df8b20d3b3b9dbff4d043be84ae488f8d shell> echo 79020296790075fc8e36835e045c513df8b20d3b3b9dbff4d043be84ae488f8d | bx ec-to-public # generate public key 03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1 shell> echo 03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1 | bx ec-to-address # generate address n1C8nsmi4sc4hMBGgVZrnhxeFtk1sTbMZ4 ``` ### Previous transaction to be spent In Bitcoin we have this concept called UTXO (Unspent Transaction Output) which is the unspent output of a previous transaction. ```shell shell> bx fetch-tx d30de2a476060e08f4761ad99993ea1f7387bfcb3385f0d604a36a04676cdf93 transaction { hash d30de2a476060e08f4761ad99993ea1f7387bfcb3385f0d604a36a04676cdf93 inputs { input { address_hash 10924d4f0aefd6dc652ce1fe906694eba4dfc8ae previous_output { hash 264d0f5be4ebdd1102e23c4b440955b04b291c654323bdd33cd51d8989e3d54f index 1 } script "[30450221009553c91c4aaf5ab137d5ed77cbc94a2c0511461f0de51b83fc2f00202f6a6beb022029a691221e1f664fa268524565d44f9e8a5387c5c091ec55f98ad12705720e7201] [02a46fc215bb6899814dc5bd026d815017784a2c4ceb78e7befdab1d5dfd51ef1a]" sequence 4294967294 } } lock_time 1384777 outputs { output { address_hash de69e4fc748732103653236dcc31c79e87422925 script "dup hash160 [de69e4fc748732103653236dcc31c79e87422925] equalverify checksig" value 3625875580 } output { address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a script "dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig" value 65000000 } } version 2 } ``` ### Create transaction Create transaction with two parameters: input (previous transaction hash and previous transaction output index) and output (receiving address and amount to send in Satoshi). ```shell shell> bx tx-encode -i d30de2a476060e08f4761ad99993ea1f7387bfcb3385f0d604a36a04676cdf93:1 -o 2NFrxEjw5v2i7L8pm9dWjWSFpDRXmj8dBTn:64000000 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd30100000000ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000 ``` ### Sign transaction Sign the input to be spent using private key and lock script. ```shell shell> bx input-sign 79020296790075fc8e36835e045c513df8b20d3b3b9dbff4d043be84ae488f8d "dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig" 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd30100000000ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000 3045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e1367451101 ``` Create unlock script using signed endorsement and the public key then set it as transaction's input. ```shell shell> bx input-set "[3045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e1367451101] [03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1]" 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd30100000000ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd3010000006b483045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e13674511012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000 ``` ### Validate transaction Validate input with public key, lock script and signed endorsement. ```shell shell> bx input-validate 03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1 "dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig" 3045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e1367451101 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd3010000006b483045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e13674511012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000 The endorsement is valid. ``` Validate encoded transaction as a whole. ```shell shell> bx validate-tx 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd3010000006b483045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e13674511012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000 The transaction is valid. ``` ### Broadcast transaction Broadcast the transaction to network. ```shell bx send-tx 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd3010000006b483045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e13674511012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000 Sent transaction. ``` Check address and transaction history. ```shell shell> bx fetch-history n1C8nsmi4sc4hMBGgVZrnhxeFtk1sTbMZ4 transfers { transfer { received { hash d30de2a476060e08f4761ad99993ea1f7387bfcb3385f0d604a36a04676cdf93 height 1384780 index 1 } spent { hash fb8c52b201eb474ea3b2cb1f482cf4f774f710c711267818fbdd4763a5ca38b9 height 1384802 index 0 } value 65000000 } } ``` ## B. The hard way Now lets get down to real business and craft our own transaction starting with a few utility methods that we are going to use along the way. Two methods to convert big numbers to bytes string and vice-versa, padding with `0x00` to satisfy the required length if any. ```ruby def bytes_to_bignum(bytes_string) bytes_string.bytes.reduce { |n, b| (n << 8) + b } end def bignum_to_bytes(n, length=nil) a = [] while n > 0 a << (n & 0xFF) n >>= 8 end a.fill 0x00, a.length, length - a.length if length a.reverse.pack('C*') end ``` Base58 encoding / decoding methods, Bitcoin address decoding to Hash160 (hashing twice with sha256 then ripe160) and build Bitcoin script based on destination address that can be Pay-to-PublicKey-Hash or Pay-to-Script-hash. ```ruby def bitcoin_base58_encode(ripe160_hash) alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' value = ripe160_hash.to_i 16 output = '' while value > 0 remainder = value % 58 value /= 58 output += alphabet[remainder] end output += alphabet[0] * [ripe160_hash].pack('H*').bytes.find_index{|b| b != 0} output.reverse end def bitcoin_base58_decode(address) alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' int_val = 0 address.reverse.chars.each_with_index do |char, index| char_index = alphabet.index(char) int_val += char_index * 58**index end bignum_to_bytes(int_val, 25).unpack('H*').first end def bitcoin_address_decode(address) wrap_encode = bitcoin_base58_decode address wrap_encode[2, 40] end def bitcoin_script(address) hash160 = bitcoin_address_decode address if address.start_with? '2' "OP_HASH160 #{hash160} OP_EQUAL" else "OP_DUP OP_HASH160 #{hash160} OP_EQUALVERIFY OP_CHECKSIG" end end ``` Multiple utility methods to transform different data types into hex string. ```ruby class Struct OPCODES = { 'OP_DUP' => 0x76, 'OP_HASH160' => 0xA9, 'OP_EQUAL' => 0x87, 'OP_EQUALVERIFY' => 0x88, 'OP_CHECKSIG' => 0xAC }.freeze def opcode(token) raise "opcode #{token} not found" unless OPCODES.include?(token) OPCODES[token].to_s 16 end def data(token) bin_size = hex_size token byte_to_hex(bin_size) + token end def hex_size(hex) [hex].pack('H*').size end def to_hex(binary_bytes) binary_bytes.unpack('H*').first end def hash_to_hex(value) to_hex [value].pack('H*').reverse end def int_to_hex(value) to_hex [value].pack('V') end def byte_to_hex(value) to_hex [value].pack('C') end def long_to_hex(value) to_hex [value].pack('Q<') end def script_to_hex(script_string) script_string.split.map { |token| token.start_with?('OP') ? opcode(token) : data(token) }.join end def sha256(hex) Digest::SHA256.hexdigest([hex].pack('H*')) end end ``` Now, lets check the previous transaction that we want to spend. ```shell shell> bx fetch-transaction ea8a64e122304637e8da016836e9afd59fc1179dfa15affc40d63b34e7db0cec transaction { hash ea8a64e122304637e8da016836e9afd59fc1179dfa15affc40d63b34e7db0cec inputs { input { address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a previous_output { hash 6b22d8a69432774ebbc00566755ff8da241be83c1b364ca177e241e23a0e111c index 0 } script "[3045022100e4c449be7643140b9a62635afe8f99406311372f6ad4215d19a6d0b0ea306c7902203c6966502dba43b86d34d9252adb7632632bce1cf83ed721b5a1ac00e9e0f48a01] [03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1]" sequence 4294967295 } } lock_time 0 outputs { output { address_hash ad99d5964d9180d501c8863f4bcd7b04f0766787 script "dup hash160 [ad99d5964d9180d501c8863f4bcd7b04f0766787] equalverify checksig" value 1000000 } output { address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a script "dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig" value 23990000 } } version 1 } ``` Build transaction input from previous UTXO (Unspent Transaction Output): value, tx hash and output index. ```ruby Input = Struct.new :value, :tx_hash, :index, :unlock_script, :sequence do def initialize(value, tx_hash, index, unlock_script: '', sequence: 0xfffffffff) super value, tx_hash, index, unlock_script, sequence end def serialize script_hex = script_to_hex(unlock_script) hash_to_hex(tx_hash) + int_to_hex(index) + byte_to_hex(hex_size(script_hex)) + script_hex + int_to_hex(sequence) end end input = Input.new 23_990_000, 'ea8a64e122304637e8da016836e9afd59fc1179dfa15affc40d63b34e7db0cec', 1 ``` Build transaction output with output value and lock script. ```ruby Output = Struct.new :value, :lock_script do def serialize script_hex = script_to_hex(lock_script) long_to_hex(value) + byte_to_hex(hex_size(script_hex)) + script_hex end end output_script = bitcoin_script '2N959B4qEPkce8jbzQC7EQaS6uaEBB9YTgQ' output = Output.new 1_000_000, output_script ``` Build the second output which is the 'change' transaction. ```ruby change_value = input.value - output.value - 10_000 change_script = bitcoin_script 'n1C8nsmi4sc4hMBGgVZrnhxeFtk1sTbMZ4' change = Output.new change_value, change_script ``` Before creating the actual transction lets introduce a few elliptic curve methods methods and parameters that we all know and love already. ```ruby EC_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 EC_Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 EC_p = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1 EC_n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 def extended_euclidean_algorithm(a, b) s, old_s = 0, 1 t, old_t = 1, 0 r, old_r = b, a while r != 0 quotient = old_r / r old_r, r = r, old_r - quotient * r old_s, s = s, old_s - quotient * s old_t, t = t, old_t - quotient * t end [old_r, old_s, old_t] end def inverse(n, p) gcd, x, y = extended_euclidean_algorithm(n, p) (n * x + p * y) % p == gcd || raise('invalid gcd') gcd == 1 || raise('no multiplicative inverse') x % p end def ec_double(px, py, pn) i_2y = inverse(2 * py, pn) slope = (3 * px**2 * i_2y) % pn x = (slope**2 - 2 * px) % pn y = (slope*(px - x) - py) % pn [x, y] end def ec_add(ax, ay, bx, by, pn) return [ax, ay] if bx == 0 && by == 0 return [bx, by] if ax == 0 && ay == 0 return ec_double(ax, ay, pn) if ax == bx && ay == by i_bax = inverse(ax - bx, pn) slope = ((ay - by) * i_bax) % pn x = (slope**2 - ax - bx) % pn y = (slope*(ax - x) - ay) % pn [x, y] end def ec_multiply(m, px, py, pn) nx, ny = px, py qx, qy = 0, 0 while m > 0 qx, qy = ec_add qx, qy, nx, ny, pn if m&1 == 1 nx, ny = ec_double nx, ny, pn m >>= 1 end [qx, qy] end ``` And these are the core methods of Elliptic Curve Digital Signature Algorithm (ECDSA), the sign/verify methods with DER signature encoding. ```ruby def ecdsa_sign(private_key, digest, temp_key = nil) temp_key ||= 1 + SecureRandom.random_number(EC_n - 1) rx, _ry = ec_multiply(temp_key, EC_Gx, EC_Gy, EC_p) r = rx % EC_n r > 0 || raise('r is zero, try again new temp key') i_tk = inverse temp_key, EC_n m = bytes_to_bignum digest s = (i_tk * (m + r * private_key)) % EC_n s > 0 || raise('s is zero, try again new temp key') [r, s] end def ecdsa_verify?(px, py, digest, signature) r, s = signature i_s = inverse s, EC_n m = bytes_to_bignum digest u1 = i_s * m % EC_n u2 = i_s * r % EC_n u1Gx, u1Gy = ec_multiply u1, EC_Gx, EC_Gy, EC_p u2Px, u2Py = ec_multiply u2, px, py, EC_p rx, _ry = ec_add u1Gx, u1Gy, u2Px, u2Py, EC_p r == rx end Der = Struct.new :der, :length, :ri, :rl, :r, :si, :sl, :s, :sighash_type do def initialize(der: 0x30, length: 0x45, ri: 0x02, rl: 0x21, r: nil, si: 0x02, sl: 0x20, s: nil, sighash_type: 0x01) super der, length, ri, rl, r, si, sl, s, sighash_type end def serialize byte_to_hex(der) + byte_to_hex(length) + byte_to_hex(ri) + byte_to_hex(rl) + to_hex(bignum_to_bytes(r, 33)) + byte_to_hex(si) + byte_to_hex(sl) + to_hex(bignum_to_bytes(s, 32)) + byte_to_hex(sighash_type) end def self.parse(signature) fields = *[signature].pack('H*').unpack('CCCCH66CCH64C') Der.new r: fields[4], s: fields[7], sighash_type: fields[8] end end ``` We are getting there, build Bitcoin transaction passing in the input and the two outputs. ```ruby Transaction = Struct.new :version, :inputs, :outputs, :locktime do def serialize inputs_hex = inputs.map(&:serialize).join outputs_hex = outputs.map(&:serialize).join int_to_hex(version) + byte_to_hex(inputs.size) + inputs_hex + byte_to_hex(outputs.size) + outputs_hex + int_to_hex(locktime) end def hash hash_to_hex sha256(sha256(serialize)) end def signature_hash(lock_script = nil, sighash_type = 0x1) inputs.first.unlock_script = lock_script if lock_script hash = sha256(sha256(serialize + int_to_hex(sighash_type))) [hash].pack('H*') end def sign(private_key, public_key, lock_script, sighash_type = 0x01) bytes_string = signature_hash lock_script, sighash_type r, s = ecdsa_sign private_key, bytes_string der = Der.new r: r, s: s inputs.first.unlock_script = "#{der.serialize} #{public_key}" serialize end end transaction = Transaction.new 1, [input], [output, change], 0 ``` Finally, to sign the transaction we need 3 things: private key, public key and the lock script of previous UTXO to spend. ```ruby private_key = 0x79020296790075fc8e36835e045c513df8b20d3b3b9dbff4d043be84ae488f8d public_key = '03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1' lock_script = bitcoin_script 'n1C8nsmi4sc4hMBGgVZrnhxeFtk1sTbMZ4' tx_hex = transaction.sign private_key, public_key, lock_script puts "TX hash: #{transaction.hash}" puts "TX hex: #{tx_hex}" ``` And VOILA! take the returned transaction hex and decode/validate it: ```shell shell> bx tx-decode 0100000001ec0cdbe7343bd640fcaf15fa9d17c19fd5afe9366801dae837463022e1648aea010000006b483045022100c1c85b5865f64f8f18c54f028a50942cd21cbda9c4a5f9296132defe51017c640220304793e361e71b3bae812923ca4aa5481a2fead05a73583ad5d930e7229f562f012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff0240420f000000000017a914ad99d5964d9180d501c8863f4bcd7b04f076678787a0a55e01000000001976a914d7d35ff2ed9cbc95e689338af8cd1db133be6a4a88ac00000000 transaction { hash c218dc394fef23ab9652ed6fd49539aa5dfb4f0153127b5c433032918948e60b inputs { input { address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a previous_output { hash ea8a64e122304637e8da016836e9afd59fc1179dfa15affc40d63b34e7db0cec index 1 } script "[3045022100c1c85b5865f64f8f18c54f028a50942cd21cbda9c4a5f9296132defe51017c640220304793e361e71b3bae812923ca4aa5481a2fead05a73583ad5d930e7229f562f01] [03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1]" sequence 4294967295 } } lock_time 0 outputs { output { address_hash ad99d5964d9180d501c8863f4bcd7b04f0766787 script "hash160 [ad99d5964d9180d501c8863f4bcd7b04f0766787] equal" value 1000000 } output { address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a script "dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig" value 22980000 } } version 1 } ``` then submit it to Bitcoin testnet network via: - [Broadcast TX](https://testnet.blockchain.info/pushtx) - or using `bitcoin-cli` command line tool ```shell shell> bitcoin-cli -testnet sendrawtransaction 0100000001ec0cdbe7343bd640fcaf15fa9d17c19fd5afe9366801dae837463022e1648aea010000006b483045022100c1c85b5865f64f8f18c54f028a50942cd21cbda9c4a5f9296132defe51017c640220304793e361e71b3bae812923ca4aa5481a2fead05a73583ad5d930e7229f562f012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff0240420f000000000017a914ad99d5964d9180d501c8863f4bcd7b04f076678787a0a55e01000000001976a914d7d35ff2ed9cbc95e689338af8cd1db133be6a4a88ac00000000 ``` ## C. Conclusions Creating transaction is a bit more difficult than generating a Bitcoin address that we saw in Part 1 but it is all possible once you understand the basics of Bitcoin like UTXOs, script and transactions. ## D. References Here are the most important references but feel free to get in touch for more information. * [OP_CHECKSIG](https://en.bitcoin.it/wiki/OP_CHECKSIG) * [Bitcoin Script](https://en.bitcoin.it/wiki/Script) * [Address prefixes](https://en.bitcoin.it/wiki/List_of_address_prefixes) * [Libbitcoin-explorer](https://github.com/libbitcoin/libbitcoin-explorer/wiki) The very end. |
| json metadata | {"tags":["bitcoin","cryptography","ecdsa","utxo","transaction"],"links":["https://testnet.blockchain.info/pushtx","https://en.bitcoin.it/wiki/OP_CHECKSIG","https://en.bitcoin.it/wiki/Script","https://en.bitcoin.it/wiki/List_of_address_prefixes","https://github.com/libbitcoin/libbitcoin-explorer/wiki"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | bitcoin |
| permlink | the-hard-way-bitcoin-transactions |
| title | The hard way - Bitcoin: transactions |
| Transaction Info | Block #27606425/Trx 50830e572d20a3511dcd7b863daaee39d77d99b9 |
View Raw JSON Data
{
"block": 27606425,
"op": [
"comment",
{
"author": "icostan",
"body": "# The hard way - Bitcoin: Transaction\n\n\nThis is Part 2 of 'The hard way - Bitcoin' series and I will start with 'the easy way' section first because even this gets a bit complex, then will continue with the hard stuff, crafting a Bitcoin transaction from scratch using basic math and cryptography.\n\n## A. The easy way\n\n### Create private key, public key and address\n\nWe are going to generate private key, public key and Bitcoin testnet address to be used in this article.\n\n```shell\nshell> bx seed # generate seed\n27634686aa8838acaa68e27aea6c072534394ce411cb7d75\n\nshell> echo 27634686aa8838acaa68e27aea6c072534394ce411cb7d75 | bx ec-new # generate private key\n79020296790075fc8e36835e045c513df8b20d3b3b9dbff4d043be84ae488f8d\n\nshell> echo 79020296790075fc8e36835e045c513df8b20d3b3b9dbff4d043be84ae488f8d | bx ec-to-public # generate public key\n03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1\n\nshell> echo 03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1 | bx ec-to-address # generate address\nn1C8nsmi4sc4hMBGgVZrnhxeFtk1sTbMZ4\n```\n### Previous transaction to be spent\n\nIn Bitcoin we have this concept called UTXO (Unspent Transaction Output) which is the unspent output of a previous transaction.\n\n```shell\nshell> bx fetch-tx d30de2a476060e08f4761ad99993ea1f7387bfcb3385f0d604a36a04676cdf93\ntransaction\n{\n hash d30de2a476060e08f4761ad99993ea1f7387bfcb3385f0d604a36a04676cdf93\n inputs\n {\n input\n {\n address_hash 10924d4f0aefd6dc652ce1fe906694eba4dfc8ae\n previous_output\n {\n hash 264d0f5be4ebdd1102e23c4b440955b04b291c654323bdd33cd51d8989e3d54f\n index 1\n }\n script \"[30450221009553c91c4aaf5ab137d5ed77cbc94a2c0511461f0de51b83fc2f00202f6a6beb022029a691221e1f664fa268524565d44f9e8a5387c5c091ec55f98ad12705720e7201] [02a46fc215bb6899814dc5bd026d815017784a2c4ceb78e7befdab1d5dfd51ef1a]\"\n sequence 4294967294\n }\n }\n lock_time 1384777\n outputs\n {\n output\n {\n address_hash de69e4fc748732103653236dcc31c79e87422925\n script \"dup hash160 [de69e4fc748732103653236dcc31c79e87422925] equalverify checksig\"\n value 3625875580\n }\n output\n {\n address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a\n script \"dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig\"\n value 65000000\n }\n }\n version 2\n}\n```\n\n### Create transaction\n\nCreate transaction with two parameters: input (previous transaction hash and previous transaction output index) and output (receiving address and amount to send in Satoshi).\n\n```shell\nshell> bx tx-encode -i d30de2a476060e08f4761ad99993ea1f7387bfcb3385f0d604a36a04676cdf93:1 -o 2NFrxEjw5v2i7L8pm9dWjWSFpDRXmj8dBTn:64000000\n010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd30100000000ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000\n```\n\n### Sign transaction\n\nSign the input to be spent using private key and lock script.\n\n```shell\nshell> bx input-sign 79020296790075fc8e36835e045c513df8b20d3b3b9dbff4d043be84ae488f8d \"dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig\" 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd30100000000ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000\n3045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e1367451101\n```\n\nCreate unlock script using signed endorsement and the public key then set it as transaction's input.\n\n```shell\nshell> bx input-set \"[3045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e1367451101] [03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1]\" 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd30100000000ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000\n010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd3010000006b483045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e13674511012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000\n```\n\n### Validate transaction\n\nValidate input with public key, lock script and signed endorsement.\n\n```shell\nshell> bx input-validate 03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1 \"dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig\" 3045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e1367451101 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd3010000006b483045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e13674511012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000\nThe endorsement is valid.\n```\n\nValidate encoded transaction as a whole.\n\n```shell\nshell> bx validate-tx 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd3010000006b483045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e13674511012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000\nThe transaction is valid.\n```\n\n### Broadcast transaction\n\nBroadcast the transaction to network.\n\n```shell\nbx send-tx 010000000193df6c67046aa304d6f08533cbbf87731fea9399d91a76f4080e0676a4e20dd3010000006b483045022100b290086350a59ce28dd80cc89eac80eac097c20a50ed8c4f35b1ecbed789b65c02200129f4c34a9b05705d4f5e55acff0ce44b5565ab4a8c7faa4a74cf5e13674511012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff010090d0030000000017a914f81498040e79014455a5e8f7bd39bce5428121d38700000000\nSent transaction.\n```\n\nCheck address and transaction history.\n\n```shell\nshell> bx fetch-history n1C8nsmi4sc4hMBGgVZrnhxeFtk1sTbMZ4\ntransfers\n{\n transfer\n {\n received\n {\n hash d30de2a476060e08f4761ad99993ea1f7387bfcb3385f0d604a36a04676cdf93\n height 1384780\n index 1\n }\n spent\n {\n hash fb8c52b201eb474ea3b2cb1f482cf4f774f710c711267818fbdd4763a5ca38b9\n height 1384802\n index 0\n }\n value 65000000\n }\n}\n```\n\n## B. The hard way\n\nNow lets get down to real business and craft our own transaction starting with a few utility methods that we are going to use along the way.\n\nTwo methods to convert big numbers to bytes string and vice-versa, padding with `0x00` to satisfy the required length if any.\n\n```ruby\ndef bytes_to_bignum(bytes_string)\n bytes_string.bytes.reduce { |n, b| (n << 8) + b }\nend\ndef bignum_to_bytes(n, length=nil)\n a = []\n while n > 0\n a << (n & 0xFF)\n n >>= 8\n end\n a.fill 0x00, a.length, length - a.length if length\n a.reverse.pack('C*')\nend\n```\n\nBase58 encoding / decoding methods, Bitcoin address decoding to Hash160 (hashing twice with sha256 then ripe160) and build Bitcoin script based on destination address that can be Pay-to-PublicKey-Hash or Pay-to-Script-hash.\n\n```ruby\ndef bitcoin_base58_encode(ripe160_hash)\n alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'\n value = ripe160_hash.to_i 16\n output = ''\n while value > 0\n remainder = value % 58\n value /= 58\n output += alphabet[remainder]\n end\n output += alphabet[0] * [ripe160_hash].pack('H*').bytes.find_index{|b| b != 0}\n output.reverse\nend\ndef bitcoin_base58_decode(address)\n alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'\n int_val = 0\n address.reverse.chars.each_with_index do |char, index|\n char_index = alphabet.index(char)\n int_val += char_index * 58**index\n end\n bignum_to_bytes(int_val, 25).unpack('H*').first\nend\ndef bitcoin_address_decode(address)\n wrap_encode = bitcoin_base58_decode address\n wrap_encode[2, 40]\nend\ndef bitcoin_script(address)\n hash160 = bitcoin_address_decode address\n if address.start_with? '2'\n \"OP_HASH160 #{hash160} OP_EQUAL\"\n else\n \"OP_DUP OP_HASH160 #{hash160} OP_EQUALVERIFY OP_CHECKSIG\"\n end\nend\n```\n\nMultiple utility methods to transform different data types into hex string.\n\n```ruby\nclass Struct\n OPCODES = {\n 'OP_DUP' => 0x76,\n 'OP_HASH160' => 0xA9,\n 'OP_EQUAL' => 0x87,\n 'OP_EQUALVERIFY' => 0x88,\n 'OP_CHECKSIG' => 0xAC\n }.freeze\n def opcode(token)\n raise \"opcode #{token} not found\" unless OPCODES.include?(token)\n OPCODES[token].to_s 16\n end\n def data(token)\n bin_size = hex_size token\n byte_to_hex(bin_size) + token\n end\n def hex_size(hex)\n [hex].pack('H*').size\n end\n def to_hex(binary_bytes)\n binary_bytes.unpack('H*').first\n end\n def hash_to_hex(value)\n to_hex [value].pack('H*').reverse\n end\n def int_to_hex(value)\n to_hex [value].pack('V')\n end\n def byte_to_hex(value)\n to_hex [value].pack('C')\n end\n def long_to_hex(value)\n to_hex [value].pack('Q<')\n end\n def script_to_hex(script_string)\n script_string.split.map { |token| token.start_with?('OP') ? opcode(token) : data(token) }.join\n end\n def sha256(hex)\n Digest::SHA256.hexdigest([hex].pack('H*'))\n end\nend\n```\n\nNow, lets check the previous transaction that we want to spend.\n\n```shell\nshell> bx fetch-transaction ea8a64e122304637e8da016836e9afd59fc1179dfa15affc40d63b34e7db0cec\n\ntransaction\n{\n hash ea8a64e122304637e8da016836e9afd59fc1179dfa15affc40d63b34e7db0cec\n inputs\n {\n input\n {\n address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a\n previous_output\n {\n hash 6b22d8a69432774ebbc00566755ff8da241be83c1b364ca177e241e23a0e111c\n index 0\n }\n script \"[3045022100e4c449be7643140b9a62635afe8f99406311372f6ad4215d19a6d0b0ea306c7902203c6966502dba43b86d34d9252adb7632632bce1cf83ed721b5a1ac00e9e0f48a01] [03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1]\"\n sequence 4294967295\n }\n }\n lock_time 0\n outputs\n {\n output\n {\n address_hash ad99d5964d9180d501c8863f4bcd7b04f0766787\n script \"dup hash160 [ad99d5964d9180d501c8863f4bcd7b04f0766787] equalverify checksig\"\n value 1000000\n }\n output\n {\n address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a\n script \"dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig\"\n value 23990000\n }\n }\n version 1\n}\n```\n\nBuild transaction input from previous UTXO (Unspent Transaction Output): value, tx hash and output index.\n\n```ruby\nInput = Struct.new :value, :tx_hash, :index, :unlock_script, :sequence do\n def initialize(value, tx_hash, index, unlock_script: '', sequence: 0xfffffffff)\n super value, tx_hash, index, unlock_script, sequence\n end\n def serialize\n script_hex = script_to_hex(unlock_script)\n hash_to_hex(tx_hash) + int_to_hex(index) +\n byte_to_hex(hex_size(script_hex)) + script_hex + int_to_hex(sequence)\n end\nend\ninput = Input.new 23_990_000, 'ea8a64e122304637e8da016836e9afd59fc1179dfa15affc40d63b34e7db0cec', 1\n```\n\nBuild transaction output with output value and lock script.\n\n```ruby\nOutput = Struct.new :value, :lock_script do\n def serialize\n script_hex = script_to_hex(lock_script)\n long_to_hex(value) + byte_to_hex(hex_size(script_hex)) + script_hex\n end\nend\noutput_script = bitcoin_script '2N959B4qEPkce8jbzQC7EQaS6uaEBB9YTgQ'\noutput = Output.new 1_000_000, output_script\n```\n\nBuild the second output which is the 'change' transaction.\n\n```ruby\nchange_value = input.value - output.value - 10_000\nchange_script = bitcoin_script 'n1C8nsmi4sc4hMBGgVZrnhxeFtk1sTbMZ4'\nchange = Output.new change_value, change_script\n```\n\nBefore creating the actual transction lets introduce a few elliptic curve methods methods and parameters that we all know and love already.\n\n```ruby\nEC_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798\nEC_Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8\nEC_p = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1\nEC_n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141\n\ndef extended_euclidean_algorithm(a, b)\n s, old_s = 0, 1\n t, old_t = 1, 0\n r, old_r = b, a\n while r != 0\n quotient = old_r / r\n old_r, r = r, old_r - quotient * r\n old_s, s = s, old_s - quotient * s\n old_t, t = t, old_t - quotient * t\n end\n [old_r, old_s, old_t]\nend\ndef inverse(n, p)\n gcd, x, y = extended_euclidean_algorithm(n, p)\n (n * x + p * y) % p == gcd || raise('invalid gcd')\n gcd == 1 || raise('no multiplicative inverse')\n x % p\nend\ndef ec_double(px, py, pn)\n i_2y = inverse(2 * py, pn)\n slope = (3 * px**2 * i_2y) % pn\n x = (slope**2 - 2 * px) % pn\n y = (slope*(px - x) - py) % pn\n [x, y]\nend\ndef ec_add(ax, ay, bx, by, pn)\n return [ax, ay] if bx == 0 && by == 0\n return [bx, by] if ax == 0 && ay == 0\n return ec_double(ax, ay, pn) if ax == bx && ay == by\n\n i_bax = inverse(ax - bx, pn)\n slope = ((ay - by) * i_bax) % pn\n x = (slope**2 - ax - bx) % pn\n y = (slope*(ax - x) - ay) % pn\n [x, y]\nend\ndef ec_multiply(m, px, py, pn)\n nx, ny = px, py\n qx, qy = 0, 0\n while m > 0\n qx, qy = ec_add qx, qy, nx, ny, pn if m&1 == 1\n nx, ny = ec_double nx, ny, pn\n m >>= 1\n end\n [qx, qy]\nend\n```\n\nAnd these are the core methods of Elliptic Curve Digital Signature Algorithm (ECDSA), the sign/verify methods with DER signature encoding.\n\n```ruby\ndef ecdsa_sign(private_key, digest, temp_key = nil)\n temp_key ||= 1 + SecureRandom.random_number(EC_n - 1)\n rx, _ry = ec_multiply(temp_key, EC_Gx, EC_Gy, EC_p)\n r = rx % EC_n\n r > 0 || raise('r is zero, try again new temp key')\n i_tk = inverse temp_key, EC_n\n m = bytes_to_bignum digest\n s = (i_tk * (m + r * private_key)) % EC_n\n s > 0 || raise('s is zero, try again new temp key')\n [r, s]\nend\ndef ecdsa_verify?(px, py, digest, signature)\n r, s = signature\n i_s = inverse s, EC_n\n m = bytes_to_bignum digest\n u1 = i_s * m % EC_n\n u2 = i_s * r % EC_n\n u1Gx, u1Gy = ec_multiply u1, EC_Gx, EC_Gy, EC_p\n u2Px, u2Py = ec_multiply u2, px, py, EC_p\n rx, _ry = ec_add u1Gx, u1Gy, u2Px, u2Py, EC_p\n r == rx\nend\nDer = Struct.new :der, :length, :ri, :rl, :r, :si, :sl, :s, :sighash_type do\n def initialize(der: 0x30, length: 0x45, ri: 0x02, rl: 0x21, r: nil, si: 0x02, sl: 0x20, s: nil, sighash_type: 0x01)\n super der, length, ri, rl, r, si, sl, s, sighash_type\n end\n def serialize\n byte_to_hex(der) + byte_to_hex(length) +\n byte_to_hex(ri) + byte_to_hex(rl) + to_hex(bignum_to_bytes(r, 33)) +\n byte_to_hex(si) + byte_to_hex(sl) + to_hex(bignum_to_bytes(s, 32)) +\n byte_to_hex(sighash_type)\n end\n def self.parse(signature)\n fields = *[signature].pack('H*').unpack('CCCCH66CCH64C')\n Der.new r: fields[4], s: fields[7], sighash_type: fields[8]\n end\nend\n```\n\nWe are getting there, build Bitcoin transaction passing in the input and the two outputs.\n\n```ruby\nTransaction = Struct.new :version, :inputs, :outputs, :locktime do\n def serialize\n inputs_hex = inputs.map(&:serialize).join\n outputs_hex = outputs.map(&:serialize).join\n int_to_hex(version) + byte_to_hex(inputs.size) + inputs_hex +\n byte_to_hex(outputs.size) + outputs_hex + int_to_hex(locktime)\n end\n def hash\n hash_to_hex sha256(sha256(serialize))\n end\n def signature_hash(lock_script = nil, sighash_type = 0x1)\n inputs.first.unlock_script = lock_script if lock_script\n hash = sha256(sha256(serialize + int_to_hex(sighash_type)))\n [hash].pack('H*')\n end\n def sign(private_key, public_key, lock_script, sighash_type = 0x01)\n bytes_string = signature_hash lock_script, sighash_type\n r, s = ecdsa_sign private_key, bytes_string\n der = Der.new r: r, s: s\n inputs.first.unlock_script = \"#{der.serialize} #{public_key}\"\n serialize\n end\nend\ntransaction = Transaction.new 1, [input], [output, change], 0\n```\n\nFinally, to sign the transaction we need 3 things: private key, public key and the lock script of previous UTXO to spend.\n\n```ruby\nprivate_key = 0x79020296790075fc8e36835e045c513df8b20d3b3b9dbff4d043be84ae488f8d\npublic_key = '03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1'\nlock_script = bitcoin_script 'n1C8nsmi4sc4hMBGgVZrnhxeFtk1sTbMZ4'\n\ntx_hex = transaction.sign private_key, public_key, lock_script\nputs \"TX hash: #{transaction.hash}\"\nputs \"TX hex: #{tx_hex}\"\n```\n\nAnd VOILA! take the returned transaction hex and decode/validate it:\n\n```shell\nshell> bx tx-decode 0100000001ec0cdbe7343bd640fcaf15fa9d17c19fd5afe9366801dae837463022e1648aea010000006b483045022100c1c85b5865f64f8f18c54f028a50942cd21cbda9c4a5f9296132defe51017c640220304793e361e71b3bae812923ca4aa5481a2fead05a73583ad5d930e7229f562f012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff0240420f000000000017a914ad99d5964d9180d501c8863f4bcd7b04f076678787a0a55e01000000001976a914d7d35ff2ed9cbc95e689338af8cd1db133be6a4a88ac00000000\n\ntransaction\n{\n hash c218dc394fef23ab9652ed6fd49539aa5dfb4f0153127b5c433032918948e60b\n inputs\n {\n input\n {\n address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a\n previous_output\n {\n hash ea8a64e122304637e8da016836e9afd59fc1179dfa15affc40d63b34e7db0cec\n index 1\n }\n script \"[3045022100c1c85b5865f64f8f18c54f028a50942cd21cbda9c4a5f9296132defe51017c640220304793e361e71b3bae812923ca4aa5481a2fead05a73583ad5d930e7229f562f01] [03996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1]\"\n sequence 4294967295\n }\n }\n lock_time 0\n outputs\n {\n output\n {\n address_hash ad99d5964d9180d501c8863f4bcd7b04f0766787\n script \"hash160 [ad99d5964d9180d501c8863f4bcd7b04f0766787] equal\"\n value 1000000\n }\n output\n {\n address_hash d7d35ff2ed9cbc95e689338af8cd1db133be6a4a\n script \"dup hash160 [d7d35ff2ed9cbc95e689338af8cd1db133be6a4a] equalverify checksig\"\n value 22980000\n }\n }\n version 1\n}\n\n```\n\nthen submit it to Bitcoin testnet network via:\n\n- [Broadcast TX](https://testnet.blockchain.info/pushtx)\n- or using `bitcoin-cli` command line tool\n\n```shell\nshell> bitcoin-cli -testnet sendrawtransaction 0100000001ec0cdbe7343bd640fcaf15fa9d17c19fd5afe9366801dae837463022e1648aea010000006b483045022100c1c85b5865f64f8f18c54f028a50942cd21cbda9c4a5f9296132defe51017c640220304793e361e71b3bae812923ca4aa5481a2fead05a73583ad5d930e7229f562f012103996c918f74f0a6f1aeed99ebd81ab8eed8df99bc96fc082b20839259d332bad1ffffffff0240420f000000000017a914ad99d5964d9180d501c8863f4bcd7b04f076678787a0a55e01000000001976a914d7d35ff2ed9cbc95e689338af8cd1db133be6a4a88ac00000000\n```\n\n## C. Conclusions\n\nCreating transaction is a bit more difficult than generating a Bitcoin address that we saw in Part 1 but it is all possible once you understand the basics of Bitcoin like UTXOs, script and transactions.\n\n## D. References\n\nHere are the most important references but feel free to get in touch for more information.\n\n * [OP_CHECKSIG](https://en.bitcoin.it/wiki/OP_CHECKSIG)\n * [Bitcoin Script](https://en.bitcoin.it/wiki/Script)\n * [Address prefixes](https://en.bitcoin.it/wiki/List_of_address_prefixes)\n * [Libbitcoin-explorer](https://github.com/libbitcoin/libbitcoin-explorer/wiki)\n\nThe very end.",
"json_metadata": "{\"tags\":[\"bitcoin\",\"cryptography\",\"ecdsa\",\"utxo\",\"transaction\"],\"links\":[\"https://testnet.blockchain.info/pushtx\",\"https://en.bitcoin.it/wiki/OP_CHECKSIG\",\"https://en.bitcoin.it/wiki/Script\",\"https://en.bitcoin.it/wiki/List_of_address_prefixes\",\"https://github.com/libbitcoin/libbitcoin-explorer/wiki\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "bitcoin",
"permlink": "the-hard-way-bitcoin-transactions",
"title": "The hard way - Bitcoin: transactions"
}
],
"op_in_trx": 0,
"timestamp": "2018-11-11T12:40:57",
"trx_id": "50830e572d20a3511dcd7b863daaee39d77d99b9",
"trx_in_block": 6,
"virtual_op": 0
}icostanupdated their account properties2018/11/03 07:36:00
icostanupdated their account properties
2018/11/03 07:36:00
| account | icostan |
| json metadata | {"profile":{"name":"Iulian Costan","about":"Computer geek, derivatives trader, crypto enthusiast.","website":"http://iuliancostan.com"}} |
| memo key | STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa |
| Transaction Info | Block #27370103/Trx e2b2a631efd58a7019b54d36516e6f88f665ce60 |
View Raw JSON Data
{
"block": 27370103,
"op": [
"account_update",
{
"account": "icostan",
"json_metadata": "{\"profile\":{\"name\":\"Iulian Costan\",\"about\":\"Computer geek, derivatives trader, crypto enthusiast.\",\"website\":\"http://iuliancostan.com\"}}",
"memo_key": "STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa"
}
],
"op_in_trx": 0,
"timestamp": "2018-11-03T07:36:00",
"trx_id": "e2b2a631efd58a7019b54d36516e6f88f665ce60",
"trx_in_block": 3,
"virtual_op": 0
}icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address2018/10/11 18:29:18
icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address
2018/10/11 18:29:18
| author | icostan |
| body | @@ -1,64 +1,4 @@ -# The hard way - Bitcoin: private key, public key, address%0A%0A This |
| json metadata | {"tags":["bitcoin","cryptography","elliptic-curve","math","crypto"],"links":["https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e","https://en.bitcoin.it/wiki/Secp256k1","https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored","https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication","https://en.bitcoin.it/wiki/List_of_address_prefixes","https://en.bitcoin.it/wiki/Base58Check_encoding","https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence","https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses","https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs","http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/","https://blockgeeks.com/guides/cryptocurrencies-cryptography/","https://www.coindesk.com/math-behind-bitcoin/"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | bitcoin |
| permlink | the-hard-way-bitcoin-private-key-public-key-address |
| title | The hard way - Bitcoin: private key, public key, address |
| Transaction Info | Block #26721246/Trx f3e12ef05f3010c4cbfceafceca9964e7a94589d |
View Raw JSON Data
{
"block": 26721246,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -1,64 +1,4 @@\n-# The hard way - Bitcoin: private key, public key, address%0A%0A\n This\n",
"json_metadata": "{\"tags\":[\"bitcoin\",\"cryptography\",\"elliptic-curve\",\"math\",\"crypto\"],\"links\":[\"https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e\",\"https://en.bitcoin.it/wiki/Secp256k1\",\"https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored\",\"https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication\",\"https://en.bitcoin.it/wiki/List_of_address_prefixes\",\"https://en.bitcoin.it/wiki/Base58Check_encoding\",\"https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence\",\"https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses\",\"https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\",\"http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/\",\"https://blockgeeks.com/guides/cryptocurrencies-cryptography/\",\"https://www.coindesk.com/math-behind-bitcoin/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "bitcoin",
"permlink": "the-hard-way-bitcoin-private-key-public-key-address",
"title": "The hard way - Bitcoin: private key, public key, address"
}
],
"op_in_trx": 0,
"timestamp": "2018-10-11T18:29:18",
"trx_id": "f3e12ef05f3010c4cbfceafceca9964e7a94589d",
"trx_in_block": 6,
"virtual_op": 0
}icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address2018/10/11 18:25:15
icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address
2018/10/11 18:25:15
| author | icostan |
| body | @@ -9665,17 +9665,18 @@ fo on th -e +is subject |
| json metadata | {"tags":["bitcoin","cryptography","elliptic-curve","math","crypto"],"links":["https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e","https://en.bitcoin.it/wiki/Secp256k1","https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored","https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication","https://en.bitcoin.it/wiki/List_of_address_prefixes","https://en.bitcoin.it/wiki/Base58Check_encoding","https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence","https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses","https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs","http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/","https://blockgeeks.com/guides/cryptocurrencies-cryptography/","https://www.coindesk.com/math-behind-bitcoin/"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | bitcoin |
| permlink | the-hard-way-bitcoin-private-key-public-key-address |
| title | The hard way - Bitcoin: private key, public key, address |
| Transaction Info | Block #26721165/Trx ea841f8f6d2a2bc5b3a92e8b7cb59ea684f82cc8 |
View Raw JSON Data
{
"block": 26721165,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -9665,17 +9665,18 @@\n fo on th\n-e\n+is\n subject\n",
"json_metadata": "{\"tags\":[\"bitcoin\",\"cryptography\",\"elliptic-curve\",\"math\",\"crypto\"],\"links\":[\"https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e\",\"https://en.bitcoin.it/wiki/Secp256k1\",\"https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored\",\"https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication\",\"https://en.bitcoin.it/wiki/List_of_address_prefixes\",\"https://en.bitcoin.it/wiki/Base58Check_encoding\",\"https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence\",\"https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses\",\"https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\",\"http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/\",\"https://blockgeeks.com/guides/cryptocurrencies-cryptography/\",\"https://www.coindesk.com/math-behind-bitcoin/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "bitcoin",
"permlink": "the-hard-way-bitcoin-private-key-public-key-address",
"title": "The hard way - Bitcoin: private key, public key, address"
}
],
"op_in_trx": 0,
"timestamp": "2018-10-11T18:25:15",
"trx_id": "ea841f8f6d2a2bc5b3a92e8b7cb59ea684f82cc8",
"trx_in_block": 3,
"virtual_op": 0
}icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address2018/10/11 18:24:54
icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address
2018/10/11 18:24:54
| author | icostan |
| body | @@ -9570,16 +9570,123 @@ rences%0A%0A +See the most important references below and feel free to contact me if you need more info on the subject.%0A%0A * %5BBit |
| json metadata | {"tags":["bitcoin","cryptography","elliptic-curve","math","crypto"],"links":["https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e","https://en.bitcoin.it/wiki/Secp256k1","https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored","https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication","https://en.bitcoin.it/wiki/List_of_address_prefixes","https://en.bitcoin.it/wiki/Base58Check_encoding","https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence","https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses","https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs","http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/","https://blockgeeks.com/guides/cryptocurrencies-cryptography/","https://www.coindesk.com/math-behind-bitcoin/"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | bitcoin |
| permlink | the-hard-way-bitcoin-private-key-public-key-address |
| title | The hard way - Bitcoin: private key, public key, address |
| Transaction Info | Block #26721158/Trx 8bea3ddc7e96863e534d0156006ff1bccfb8f583 |
View Raw JSON Data
{
"block": 26721158,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -9570,16 +9570,123 @@\n rences%0A%0A\n+See the most important references below and feel free to contact me if you need more info on the subject.%0A%0A\n * %5BBit\n",
"json_metadata": "{\"tags\":[\"bitcoin\",\"cryptography\",\"elliptic-curve\",\"math\",\"crypto\"],\"links\":[\"https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e\",\"https://en.bitcoin.it/wiki/Secp256k1\",\"https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored\",\"https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication\",\"https://en.bitcoin.it/wiki/List_of_address_prefixes\",\"https://en.bitcoin.it/wiki/Base58Check_encoding\",\"https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence\",\"https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses\",\"https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\",\"http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/\",\"https://blockgeeks.com/guides/cryptocurrencies-cryptography/\",\"https://www.coindesk.com/math-behind-bitcoin/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "bitcoin",
"permlink": "the-hard-way-bitcoin-private-key-public-key-address",
"title": "The hard way - Bitcoin: private key, public key, address"
}
],
"op_in_trx": 0,
"timestamp": "2018-10-11T18:24:54",
"trx_id": "8bea3ddc7e96863e534d0156006ff1bccfb8f583",
"trx_in_block": 1,
"virtual_op": 0
}icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address2018/10/11 18:23:42
icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address
2018/10/11 18:23:42
| author | icostan |
| body | @@ -233,16 +233,22 @@ In this +first section |
| json metadata | {"tags":["bitcoin","cryptography","elliptic-curve","math","crypto"],"links":["https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e","https://en.bitcoin.it/wiki/Secp256k1","https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored","https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication","https://en.bitcoin.it/wiki/List_of_address_prefixes","https://en.bitcoin.it/wiki/Base58Check_encoding","https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence","https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses","https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs","http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/","https://blockgeeks.com/guides/cryptocurrencies-cryptography/","https://www.coindesk.com/math-behind-bitcoin/"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | bitcoin |
| permlink | the-hard-way-bitcoin-private-key-public-key-address |
| title | The hard way - Bitcoin: private key, public key, address |
| Transaction Info | Block #26721134/Trx 476c413e08c40905bcffa7a15d4ec03f4f6bcbfe |
View Raw JSON Data
{
"block": 26721134,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -233,16 +233,22 @@\n In this \n+first \n section \n",
"json_metadata": "{\"tags\":[\"bitcoin\",\"cryptography\",\"elliptic-curve\",\"math\",\"crypto\"],\"links\":[\"https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e\",\"https://en.bitcoin.it/wiki/Secp256k1\",\"https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored\",\"https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication\",\"https://en.bitcoin.it/wiki/List_of_address_prefixes\",\"https://en.bitcoin.it/wiki/Base58Check_encoding\",\"https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence\",\"https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses\",\"https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\",\"http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/\",\"https://blockgeeks.com/guides/cryptocurrencies-cryptography/\",\"https://www.coindesk.com/math-behind-bitcoin/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "bitcoin",
"permlink": "the-hard-way-bitcoin-private-key-public-key-address",
"title": "The hard way - Bitcoin: private key, public key, address"
}
],
"op_in_trx": 0,
"timestamp": "2018-10-11T18:23:42",
"trx_id": "476c413e08c40905bcffa7a15d4ec03f4f6bcbfe",
"trx_in_block": 23,
"virtual_op": 0
}icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address2018/10/11 18:23:18
icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address
2018/10/11 18:23:18
| author | icostan |
| body | @@ -57,26 +57,427 @@ ss%0A%0A -## A. The hard way +This article is all about two ways of generating a Bitcoin address: the hard way using simple math and the easy way using an existing Bitcoin library.%0A%0A## A. The hard way%0A%0AIn this section I am going to use simple math functions like addition and multiplication to generate a valid Bitcoin address starting from a number, the private key and calculating everything all the way up to public key and final Bitcoin address. %0A%0A## |
| json metadata | {"tags":["bitcoin","cryptography","elliptic-curve","math","crypto"],"links":["https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e","https://en.bitcoin.it/wiki/Secp256k1","https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored","https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication","https://en.bitcoin.it/wiki/List_of_address_prefixes","https://en.bitcoin.it/wiki/Base58Check_encoding","https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence","https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses","https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs","http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/","https://blockgeeks.com/guides/cryptocurrencies-cryptography/","https://www.coindesk.com/math-behind-bitcoin/"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | bitcoin |
| permlink | the-hard-way-bitcoin-private-key-public-key-address |
| title | The hard way - Bitcoin: private key, public key, address |
| Transaction Info | Block #26721126/Trx 5923410c86041713dfc50be9b3267bae0591abdf |
View Raw JSON Data
{
"block": 26721126,
"op": [
"comment",
{
"author": "icostan",
"body": "@@ -57,26 +57,427 @@\n ss%0A%0A\n-## A. The hard way\n+This article is all about two ways of generating a Bitcoin address: the hard way using simple math and the easy way using an existing Bitcoin library.%0A%0A## A. The hard way%0A%0AIn this section I am going to use simple math functions like addition and multiplication to generate a valid Bitcoin address starting from a number, the private key and calculating everything all the way up to public key and final Bitcoin address.\n %0A%0A##\n",
"json_metadata": "{\"tags\":[\"bitcoin\",\"cryptography\",\"elliptic-curve\",\"math\",\"crypto\"],\"links\":[\"https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e\",\"https://en.bitcoin.it/wiki/Secp256k1\",\"https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored\",\"https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication\",\"https://en.bitcoin.it/wiki/List_of_address_prefixes\",\"https://en.bitcoin.it/wiki/Base58Check_encoding\",\"https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence\",\"https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses\",\"https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\",\"http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/\",\"https://blockgeeks.com/guides/cryptocurrencies-cryptography/\",\"https://www.coindesk.com/math-behind-bitcoin/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "bitcoin",
"permlink": "the-hard-way-bitcoin-private-key-public-key-address",
"title": "The hard way - Bitcoin: private key, public key, address"
}
],
"op_in_trx": 0,
"timestamp": "2018-10-11T18:23:18",
"trx_id": "5923410c86041713dfc50be9b3267bae0591abdf",
"trx_in_block": 20,
"virtual_op": 0
}2018/10/09 11:44:06
2018/10/09 11:44:06
| delegatee | icostan |
| delegator | steem |
| vesting shares | 29254.963518 VESTS |
| Transaction Info | Block #26655592/Trx f56e6681254948040d01deaf9b69b41dca772ad5 |
View Raw JSON Data
{
"block": 26655592,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "29254.963518 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2018-10-09T11:44:06",
"trx_id": "f56e6681254948040d01deaf9b69b41dca772ad5",
"trx_in_block": 3,
"virtual_op": 0
}icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address2018/10/09 10:45:00
icostanpublished a new post: the-hard-way-bitcoin-private-key-public-key-address
2018/10/09 10:45:00
| author | icostan |
| body | # The hard way - Bitcoin: private key, public key, address ## A. The hard way ### TL;DR; * private key is just a number (like a PIN code) but a very very large one, `10^77` order of magnitude (put this in context of number of atoms in the known, observable universe which is `10^80`) * public key is the result of scalar multiplication of private key and a point on Elliptic curve * Bitcoin address is derived from public key by doing SHA256 / RIPE160 hashing and adding network prefix and checksum suffix * we will generate valid Bitcoin address using two hash functions and simple math operations like addition, multiplication * copy / paste Ruby code snippets below or get the[gist](https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e) ### Elliptic Curve domain parameters First of all let's talk about the 6 domain parameters that are defined in [secp256k1](https://en.bitcoin.it/wiki/Secp256k1): p,a,b,G,n,h. Read [this Slashdot thread](https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored) if you want to dive into a little bit of conspiracy theory. #### Prime number - p The migthy prime number itself. ``` ruby ruby> p = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1 => 115792089237316195423570985008687907853269984665640564039457584007908834671663 ``` #### Elliptic Curve (EC) - a, b In general elliptic curves are defined as `y^2 = x^3 + ax + b` equation but since `a = 0` and `b = 7` it becomes `y^2 = x^3 + 7` which is the elliptic curve used in Bitcoin. #### Generator point, order and cofactor - G, n and h These 3 are all related and together they define a cyclic subgroup of elliptic curve where: * `G` is a point on EC, also called the generator or base point, `(x,y)` coordinates represented in uncompressed format as a concatenation of `x` and `y` prefixed with `04` or in compressed format as `x` coordinate prefix with `02`. * `n` is the order of subgroup generated by point `G`; in other words it is the number of points that belong to this subgroup * `h` is called cofactor and can be calculated as `N/n` where `N` is the order of the entire elliptic curve group. In this case cofactor is 1 so the order of the subgroup is equal to the order of the entire elliptic curve. ``` ruby ruby> G = '0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8' => "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8" ruby> Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 => 55066263022277343669578718895168534326250603453777594175500187360389116729240 ruby> Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 => 32670510020758816978083085130507043184471273380659243275938904335757337482424 ruby> n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 ruby> h = 1 ``` ### 0. Private key We all know that Bitcoin's private key is 256 bits long that has to be an integer between `1` and `n`, the order of subgroup. Here is my take in binary representation. ``` ruby ruby> k = 0b1100011100001010010100111101101101010001100000111111101000010011010101001010011111000000100010100011100000001111001111100100011100111011101001110011111111001101001000111111000101100001000000011010111011011001010011010001000000110001100100001011100100101 => 11253563012059685825953619222107823549092147699031672238385790369351542642469 ruby> k.to_s 16 => "18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725" ``` ### 1. Public key Now, public key is just a scalar multiplication of private key (k) and elliptic curve generator point (G) as `P = k * G`. The result is another point `(x, y)` on elliptic curve, we take that `x` coordinate, prefix it with `02` if `y` is positive or `03` if `y` is negative and there it is, the public key in compressed format. A little bit of math and a few [algorithms](https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication) that we need to use for this calculation. For scalar multiplication you can add `G` to itself `k` number of times but this will be very inefficient so we are going to use "double and add" algorithm implemented in `ec_multiply` that in turn uses `ec_add` and `ec_double`, addition and doubling operations on elliptic curves. And last, since division is not defined over finite fields we need to multiply by the `multiplicative inverse` and use `extended_euclidean_algorithm` to find the greatest common divisor. ```ruby def ec_multiply(m, px, py, pn) nx, ny = px, py qx, qy = 0, 0 while m > 0 qx, qy = ec_add qx, qy, nx, ny, pn if m&1 == 1 nx, ny = ec_double nx, ny, pn m >>= 1 end [qx, qy] end def ec_add(ax, ay, bx, by, pn) return [ax, ay] if bx == 0 && by == 0 return [bx, by] if ax == 0 && ay == 0 return ec_double(ax, ay, pn) if ax == bx && ay == by i_bax = inverse(ax - bx, pn) slope = ((ay - by) * i_bax) % pn x = (slope**2 - ax - bx) % pn y = (slope*(ax - x) - ay) % pn [x, y] end def ec_double(px, py, pn) i_2y = inverse(2 * py, pn) slope = (3 * px**2 * i_2y) % pn x = (slope**2 - 2 * px) % pn y = (slope*(px - x) - py) % pn [x, y] end def inverse(n, p) gcd, x, y = extended_euclidean_algorithm(n, p) (n * x + p * y) % p == gcd || raise('invalid gcd') gcd == 1 || raise('no multiplicative inverse') x % p end def extended_euclidean_algorithm(a, b) s, old_s = 0, 1 t, old_t = 1, 0 r, old_r = b, a while r != 0 quotient = old_r / r old_r, r = r, old_r - quotient * r old_s, s = s, old_s - quotient * s old_t, t = t, old_t - quotient * t end [old_r, old_s, old_t] end ``` And here it is, point on elliptic curve and scalar multiplication. ```ruby ruby> Px, Py = ec_multiply(k, Gx, Gy, p) => [36422191471907241029883925342251831624200921388586025344128047678873736520530, 20277110887056303803699431755396003735040374760118964734768299847012543114150] ruby> P = "#{Py > 0 ? '02' : '03'}#{Px.to_s(16)}" => "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" ``` We can easily check if resulting point is still on elliptic curve. ```ruby ((Px**3 + 7 - Py**2) % p == 0) || raise('public key point is not on the curve') ``` ### 2. SHA256 hashing Standard SHA256 hashing here, I am going to use the implementation provided in Ruby. ``` ruby ruby> require 'digest' ruby> sha256 = Digest::SHA256.hexdigest([P].pack('H*')) => "0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98" ``` ### 3. RIPEMD160 hashing Same here, nothing new, standard RIPEMD160 hashing, no point reinventing the wheel. ``` ruby ruby> ripemd160 = Digest::RMD160.hexdigest([sha256].pack('H*')) => "f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" ``` ### 4. Add version byte Here are a few but see [Bitcoin address prefixes](https://en.bitcoin.it/wiki/List_of_address_prefixes) for a complete list of all supported prefixes and resulting Base58 encodings: * 0x00 - Bitcoin address - result prefix is 1 * 0x05 - Pay-to-Script-Hash address - result prefix is 3 * 0x6F - Testnet address - resulting prefix is either m or n ``` ruby ruby> with_version = "00#{ripemd160}" => "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31" ``` ### 5.6.7. Calculate checksum Double SHA256 of previously calculated RIPEMD160 prefixed with version byte: ``` ruby ruby> checksum = Digest::SHA256.hexdigest(Digest::SHA256.digest([with_version].pack('H*')))[0, 8] => "c7f18fe8" ``` ### 8. Wrap encoding ``` ruby ruby> wrap_encode = "#{with_version}#{checksum}" => "00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8" ``` ### 9. Bitcoin address The [Base58](https://en.bitcoin.it/wiki/Base58Check_encoding) algorithm removes confusing characters like "oOiI" and also "+/" signs to make entire address selectable on double click. ```ruby def base58(binary_hash) alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' value = binary_hash.unpack('H*')[0].to_i 16 output = '' while value > 0 remainder = value % 58 value /= 58 output += alphabet[remainder] end output += alphabet[0] * binary_hash.bytes.find_index{|b| b != 0} output.reverse end ``` Base58 encoding and the final Bitcoin address: ``` ruby ruby> base58([wrap_encode].pack('H*')) => "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" ``` ## B. The easy way All the steps above can be done 'the easy way', as one-liner, using excellent [Libbitcoin Explorer](https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence) tool: ```shell shell> echo 18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725 | bx ec-to-public | bx sha256 | bx ripemd160 | bx wrap-encode | bx base58-encode 1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs ``` ## C. Conclusions And here we are, the exact same Bitcoin address used in [Bitcoin address generation](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses) tutorial is generated the hard way and the easy way. You can [check the address](https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs). # References * [Bitcoin address generation](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses) * [Elliptic curve point multiplication](https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication) * [Elliptic Curve Cryptography](http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/) * [The Science Behind Cryptocurrencies Cryptography](https://blockgeeks.com/guides/cryptocurrencies-cryptography/) * [Math behind Bitcoin](https://www.coindesk.com/math-behind-bitcoin/) |
| json metadata | {"tags":["bitcoin","cryptography","elliptic-curve","math","crypto"],"links":["https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e","https://en.bitcoin.it/wiki/Secp256k1","https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored","https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication","https://en.bitcoin.it/wiki/List_of_address_prefixes","https://en.bitcoin.it/wiki/Base58Check_encoding","https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence","https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses","https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs","http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/","https://blockgeeks.com/guides/cryptocurrencies-cryptography/","https://www.coindesk.com/math-behind-bitcoin/"],"app":"steemit/0.1","format":"markdown"} |
| parent author | |
| parent permlink | bitcoin |
| permlink | the-hard-way-bitcoin-private-key-public-key-address |
| title | The hard way - Bitcoin: private key, public key, address |
| Transaction Info | Block #26654411/Trx 585e22ba0f45dbf220e41b7256edff595b37eaf4 |
View Raw JSON Data
{
"block": 26654411,
"op": [
"comment",
{
"author": "icostan",
"body": "# The hard way - Bitcoin: private key, public key, address\n\n## A. The hard way\n\n### TL;DR;\n\n * private key is just a number (like a PIN code) but a very very large one, `10^77` order of magnitude (put this in context of number of atoms in the known, observable universe which is `10^80`)\n * public key is the result of scalar multiplication of private key and a point on Elliptic curve\n * Bitcoin address is derived from public key by doing SHA256 / RIPE160 hashing and adding network prefix and checksum suffix\n * we will generate valid Bitcoin address using two hash functions and simple math operations like addition, multiplication\n * copy / paste Ruby code snippets below or get the[gist](https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e)\n\n### Elliptic Curve domain parameters\n\nFirst of all let's talk about the 6 domain parameters that are defined in [secp256k1](https://en.bitcoin.it/wiki/Secp256k1): p,a,b,G,n,h. Read [this Slashdot thread](https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored) if you want to dive into a little bit of conspiracy theory.\n\n#### Prime number - p\n\nThe migthy prime number itself.\n\n``` ruby\nruby> p = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1\n => 115792089237316195423570985008687907853269984665640564039457584007908834671663\n```\n\n#### Elliptic Curve (EC) - a, b\n\nIn general elliptic curves are defined as `y^2 = x^3 + ax + b` equation but since `a = 0` and `b = 7` it becomes `y^2 = x^3 + 7` which is the elliptic curve used in Bitcoin.\n\n#### Generator point, order and cofactor - G, n and h\n\nThese 3 are all related and together they define a cyclic subgroup of elliptic curve where:\n\n * `G` is a point on EC, also called the generator or base point, `(x,y)` coordinates represented in uncompressed format as a concatenation of `x` and `y` prefixed with `04` or in compressed format as `x` coordinate prefix with `02`.\n * `n` is the order of subgroup generated by point `G`; in other words it is the number of points that belong to this subgroup\n * `h` is called cofactor and can be calculated as `N/n` where `N` is the order of the entire elliptic curve group. In this case cofactor is 1 so the order of the subgroup is equal to the order of the entire elliptic curve.\n\n``` ruby\nruby> G = '0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'\n => \"0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8\"\nruby> Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798\n => 55066263022277343669578718895168534326250603453777594175500187360389116729240\nruby> Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8\n => 32670510020758816978083085130507043184471273380659243275938904335757337482424\nruby> n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141\nruby> h = 1\n```\n\n### 0. Private key\n\nWe all know that Bitcoin's private key is 256 bits long that has to be an integer between `1` and `n`, the order of subgroup. Here is my take in binary representation.\n\n``` ruby\nruby> k = 0b1100011100001010010100111101101101010001100000111111101000010011010101001010011111000000100010100011100000001111001111100100011100111011101001110011111111001101001000111111000101100001000000011010111011011001010011010001000000110001100100001011100100101\n => 11253563012059685825953619222107823549092147699031672238385790369351542642469\nruby> k.to_s 16\n => \"18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725\"\n```\n\n### 1. Public key\n\nNow, public key is just a scalar multiplication of private key (k) and elliptic curve generator point (G) as `P = k * G`. The result is another point `(x, y)` on elliptic curve, we take that `x` coordinate, prefix it with `02` if `y` is positive or `03` if `y` is negative and there it is, the public key in compressed format.\n\nA little bit of math and a few [algorithms](https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication) that we need to use for this calculation. For scalar multiplication you can add `G` to itself `k` number of times but this will be very inefficient so we are going to use \"double and add\" algorithm implemented in `ec_multiply` that in turn uses `ec_add` and `ec_double`, addition and doubling operations on elliptic curves. And last, since division is not defined over finite fields we need to multiply by the `multiplicative inverse` and use `extended_euclidean_algorithm` to find the greatest common divisor.\n\n```ruby\ndef ec_multiply(m, px, py, pn)\n nx, ny = px, py\n qx, qy = 0, 0\n while m > 0\n qx, qy = ec_add qx, qy, nx, ny, pn if m&1 == 1\n nx, ny = ec_double nx, ny, pn\n m >>= 1\n end\n [qx, qy]\nend\n\ndef ec_add(ax, ay, bx, by, pn)\n return [ax, ay] if bx == 0 && by == 0\n return [bx, by] if ax == 0 && ay == 0\n return ec_double(ax, ay, pn) if ax == bx && ay == by\n\n i_bax = inverse(ax - bx, pn)\n slope = ((ay - by) * i_bax) % pn\n x = (slope**2 - ax - bx) % pn\n y = (slope*(ax - x) - ay) % pn\n [x, y]\nend\n\ndef ec_double(px, py, pn)\n i_2y = inverse(2 * py, pn)\n slope = (3 * px**2 * i_2y) % pn\n x = (slope**2 - 2 * px) % pn\n y = (slope*(px - x) - py) % pn\n [x, y]\nend\n\ndef inverse(n, p)\n gcd, x, y = extended_euclidean_algorithm(n, p)\n (n * x + p * y) % p == gcd || raise('invalid gcd')\n gcd == 1 || raise('no multiplicative inverse')\n x % p\nend\n\ndef extended_euclidean_algorithm(a, b)\n s, old_s = 0, 1\n t, old_t = 1, 0\n r, old_r = b, a\n while r != 0\n quotient = old_r / r\n old_r, r = r, old_r - quotient * r\n old_s, s = s, old_s - quotient * s\n old_t, t = t, old_t - quotient * t\n end\n [old_r, old_s, old_t]\nend\n```\n\n And here it is, point on elliptic curve and scalar multiplication.\n\n```ruby\nruby> Px, Py = ec_multiply(k, Gx, Gy, p)\n => [36422191471907241029883925342251831624200921388586025344128047678873736520530, 20277110887056303803699431755396003735040374760118964734768299847012543114150]\nruby> P = \"#{Py > 0 ? '02' : '03'}#{Px.to_s(16)}\"\n => \"0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352\"\n```\n\nWe can easily check if resulting point is still on elliptic curve.\n\n```ruby\n((Px**3 + 7 - Py**2) % p == 0) || raise('public key point is not on the curve')\n```\n\n### 2. SHA256 hashing\n\nStandard SHA256 hashing here, I am going to use the implementation provided in Ruby.\n\n``` ruby\nruby> require 'digest'\nruby> sha256 = Digest::SHA256.hexdigest([P].pack('H*'))\n => \"0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98\"\n```\n\n### 3. RIPEMD160 hashing\n\nSame here, nothing new, standard RIPEMD160 hashing, no point reinventing the wheel.\n\n``` ruby\nruby> ripemd160 = Digest::RMD160.hexdigest([sha256].pack('H*'))\n => \"f54a5851e9372b87810a8e60cdd2e7cfd80b6e31\"\n```\n\n### 4. Add version byte\n\nHere are a few but see [Bitcoin address prefixes](https://en.bitcoin.it/wiki/List_of_address_prefixes) for a complete list of all supported prefixes and resulting Base58 encodings:\n * 0x00 - Bitcoin address - result prefix is 1\n * 0x05 - Pay-to-Script-Hash address - result prefix is 3\n * 0x6F - Testnet address - resulting prefix is either m or n\n\n``` ruby\nruby> with_version = \"00#{ripemd160}\"\n => \"00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31\"\n```\n\n### 5.6.7. Calculate checksum\n\nDouble SHA256 of previously calculated RIPEMD160 prefixed with version byte:\n\n``` ruby\nruby> checksum = Digest::SHA256.hexdigest(Digest::SHA256.digest([with_version].pack('H*')))[0, 8]\n => \"c7f18fe8\"\n```\n\n### 8. Wrap encoding\n\n``` ruby\nruby> wrap_encode = \"#{with_version}#{checksum}\"\n => \"00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8\"\n```\n\n### 9. Bitcoin address\n\nThe [Base58](https://en.bitcoin.it/wiki/Base58Check_encoding) algorithm removes confusing characters like \"oOiI\" and also \"+/\" signs to make entire address selectable on double click.\n\n```ruby\ndef base58(binary_hash)\n alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'\n value = binary_hash.unpack('H*')[0].to_i 16\n output = ''\n while value > 0\n remainder = value % 58\n value /= 58\n output += alphabet[remainder]\n end\n output += alphabet[0] * binary_hash.bytes.find_index{|b| b != 0}\n output.reverse\nend\n```\n\nBase58 encoding and the final Bitcoin address:\n\n``` ruby\nruby> base58([wrap_encode].pack('H*'))\n => \"1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\"\n```\n\n## B. The easy way\n\nAll the steps above can be done 'the easy way', as one-liner, using excellent [Libbitcoin Explorer](https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence) tool:\n\n```shell\nshell> echo 18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725 | bx ec-to-public | bx sha256 | bx ripemd160 | bx wrap-encode | bx base58-encode\n1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\n```\n\n## C. Conclusions\n\nAnd here we are, the exact same Bitcoin address used in [Bitcoin address generation](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses) tutorial is generated the hard way and the easy way. You can [check the address](https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs).\n\n# References\n\n * [Bitcoin address generation](https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses)\n * [Elliptic curve point multiplication](https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication)\n * [Elliptic Curve Cryptography](http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/)\n * [The Science Behind Cryptocurrencies Cryptography](https://blockgeeks.com/guides/cryptocurrencies-cryptography/)\n * [Math behind Bitcoin](https://www.coindesk.com/math-behind-bitcoin/)",
"json_metadata": "{\"tags\":[\"bitcoin\",\"cryptography\",\"elliptic-curve\",\"math\",\"crypto\"],\"links\":[\"https://gist.github.com/icostan/231b459f610e025d31e99b0bcbd8f90e\",\"https://en.bitcoin.it/wiki/Secp256k1\",\"https://it.slashdot.org/story/13/09/11/1224252/are-the-nist-standard-elliptic-curves-back-doored\",\"https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication\",\"https://en.bitcoin.it/wiki/List_of_address_prefixes\",\"https://en.bitcoin.it/wiki/Base58Check_encoding\",\"https://github.com/libbitcoin/libbitcoin-explorer/wiki/Command-Equivalence\",\"https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses\",\"https://www.blockchain.com/btc/address/1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\",\"http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/\",\"https://blockgeeks.com/guides/cryptocurrencies-cryptography/\",\"https://www.coindesk.com/math-behind-bitcoin/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
"parent_author": "",
"parent_permlink": "bitcoin",
"permlink": "the-hard-way-bitcoin-private-key-public-key-address",
"title": "The hard way - Bitcoin: private key, public key, address"
}
],
"op_in_trx": 0,
"timestamp": "2018-10-09T10:45:00",
"trx_id": "585e22ba0f45dbf220e41b7256edff595b37eaf4",
"trx_in_block": 7,
"virtual_op": 0
}2018/05/16 20:21:18
2018/05/16 20:21:18
| delegatee | icostan |
| delegator | steem |
| vesting shares | 9140.487806 VESTS |
| Transaction Info | Block #22489927/Trx d04d8910bfc9ee4b5fc8d58de66cca0a929b47f8 |
View Raw JSON Data
{
"block": 22489927,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "9140.487806 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2018-05-16T20:21:18",
"trx_id": "d04d8910bfc9ee4b5fc8d58de66cca0a929b47f8",
"trx_in_block": 8,
"virtual_op": 0
}2018/01/09 06:39:33
2018/01/09 06:39:33
| delegatee | icostan |
| delegator | steem |
| vesting shares | 29691.478190 VESTS |
| Transaction Info | Block #18819590/Trx 682d5d33dba2261e16345b5ec212023ee98e4731 |
View Raw JSON Data
{
"block": 18819590,
"op": [
"delegate_vesting_shares",
{
"delegatee": "icostan",
"delegator": "steem",
"vesting_shares": "29691.478190 VESTS"
}
],
"op_in_trx": 0,
"timestamp": "2018-01-09T06:39:33",
"trx_id": "682d5d33dba2261e16345b5ec212023ee98e4731",
"trx_in_block": 13,
"virtual_op": 0
}icostanfollowed @chesatochi2017/11/07 12:11:48
icostanfollowed @chesatochi
2017/11/07 12:11:48
| id | follow |
| json | ["follow",{"follower":"icostan","following":"chesatochi","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #17012931/Trx e65f2cd60068110afa1501f4985f7187bc8ee822 |
View Raw JSON Data
{
"block": 17012931,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"chesatochi\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-11-07T12:11:48",
"trx_id": "e65f2cd60068110afa1501f4985f7187bc8ee822",
"trx_in_block": 17,
"virtual_op": 0
}icostanvoted for witness @jerrybanfield2017/10/29 08:07:33
icostanvoted for witness @jerrybanfield
2017/10/29 08:07:33
| account | icostan |
| approve | true |
| witness | jerrybanfield |
| Transaction Info | Block #16748911/Trx fee0b7d41d055216b50ef2a0233287944dc837c0 |
View Raw JSON Data
{
"block": 16748911,
"op": [
"account_witness_vote",
{
"account": "icostan",
"approve": true,
"witness": "jerrybanfield"
}
],
"op_in_trx": 0,
"timestamp": "2017-10-29T08:07:33",
"trx_id": "fee0b7d41d055216b50ef2a0233287944dc837c0",
"trx_in_block": 16,
"virtual_op": 0
}icostanvoted for witness @good-karma2017/10/29 08:07:15
icostanvoted for witness @good-karma
2017/10/29 08:07:15
| account | icostan |
| approve | true |
| witness | good-karma |
| Transaction Info | Block #16748905/Trx 582c5a87370f77091e413122402de47d24bf5206 |
View Raw JSON Data
{
"block": 16748905,
"op": [
"account_witness_vote",
{
"account": "icostan",
"approve": true,
"witness": "good-karma"
}
],
"op_in_trx": 0,
"timestamp": "2017-10-29T08:07:15",
"trx_id": "582c5a87370f77091e413122402de47d24bf5206",
"trx_in_block": 16,
"virtual_op": 0
}icostanfollowed @edwardthomson2017/10/29 08:05:30
icostanfollowed @edwardthomson
2017/10/29 08:05:30
| id | follow |
| json | ["follow",{"follower":"icostan","following":"edwardthomson","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #16748870/Trx 06ae72d2c05ed6a4f7c257b63a5c94aa03d6a297 |
View Raw JSON Data
{
"block": 16748870,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"edwardthomson\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-10-29T08:05:30",
"trx_id": "06ae72d2c05ed6a4f7c257b63a5c94aa03d6a297",
"trx_in_block": 2,
"virtual_op": 0
}icostanfollowed @wolfofpoloniex2017/10/08 23:03:03
icostanfollowed @wolfofpoloniex
2017/10/08 23:03:03
| id | follow |
| json | ["follow",{"follower":"icostan","following":"wolfofpoloniex","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #16162737/Trx c2471d81bb900d57d1e6370437a33af79ecf0406 |
View Raw JSON Data
{
"block": 16162737,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"wolfofpoloniex\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-10-08T23:03:03",
"trx_id": "c2471d81bb900d57d1e6370437a33af79ecf0406",
"trx_in_block": 14,
"virtual_op": 0
}2017/10/07 11:18:33
2017/10/07 11:18:33
| account | icostan |
| approve | true |
| witness | furion |
| Transaction Info | Block #16119850/Trx a7749d6cc015093cbae1d9742ef34fbfac10770c |
View Raw JSON Data
{
"block": 16119850,
"op": [
"account_witness_vote",
{
"account": "icostan",
"approve": true,
"witness": "furion"
}
],
"op_in_trx": 0,
"timestamp": "2017-10-07T11:18:33",
"trx_id": "a7749d6cc015093cbae1d9742ef34fbfac10770c",
"trx_in_block": 21,
"virtual_op": 0
}2017/10/07 11:17:48
2017/10/07 11:17:48
| id | follow |
| json | ["follow",{"follower":"icostan","following":"furion","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #16119835/Trx a7b66acd589c7d04616a4183aea471832ee24936 |
View Raw JSON Data
{
"block": 16119835,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"furion\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-10-07T11:17:48",
"trx_id": "a7b66acd589c7d04616a4183aea471832ee24936",
"trx_in_block": 13,
"virtual_op": 0
}2017/08/23 10:22:18
2017/08/23 10:22:18
| id | follow |
| json | ["follow",{"follower":"icostan","following":"chris83","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #14823432/Trx f001d6e1cfde1ce205470237ee34ea6d1e312c30 |
View Raw JSON Data
{
"block": 14823432,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"chris83\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-08-23T10:22:18",
"trx_id": "f001d6e1cfde1ce205470237ee34ea6d1e312c30",
"trx_in_block": 10,
"virtual_op": 0
}icostanfollowed @jerrybanfield2017/08/15 17:44:54
icostanfollowed @jerrybanfield
2017/08/15 17:44:54
| id | follow |
| json | ["follow",{"follower":"icostan","following":"jerrybanfield","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #14602042/Trx ceb36839af1d5a1d5831934cc06e293a3029e8d6 |
View Raw JSON Data
{
"block": 14602042,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"jerrybanfield\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-08-15T17:44:54",
"trx_id": "ceb36839af1d5a1d5831934cc06e293a3029e8d6",
"trx_in_block": 6,
"virtual_op": 0
}2017/08/12 14:16:27
2017/08/12 14:16:27
| id | follow |
| json | ["follow",{"follower":"icostan","following":"thekyle","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #14512178/Trx c0ce410282bcd28a237389a9a75f62246a209a73 |
View Raw JSON Data
{
"block": 14512178,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"thekyle\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-08-12T14:16:27",
"trx_id": "c0ce410282bcd28a237389a9a75f62246a209a73",
"trx_in_block": 1,
"virtual_op": 0
}2017/08/12 14:14:57
2017/08/12 14:14:57
| id | follow |
| json | ["follow",{"follower":"icostan","following":"dtube","what":["blog"]}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #14512148/Trx 839b08f54ecd15a65e9310a2820a1b821e841797 |
View Raw JSON Data
{
"block": 14512148,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"follow\",{\"follower\":\"icostan\",\"following\":\"dtube\",\"what\":[\"blog\"]}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-08-12T14:14:57",
"trx_id": "839b08f54ecd15a65e9310a2820a1b821e841797",
"trx_in_block": 15,
"virtual_op": 0
}icostancustom json: follow2017/08/12 14:11:21
icostancustom json: follow
2017/08/12 14:11:21
| id | follow |
| json | ["reblog",{"account":"icostan","author":"heimindanger","permlink":"introducing-dtube-a-decentralized-video-platform-using-steem-and-ipfs"}] |
| required auths | [] |
| required posting auths | ["icostan"] |
| Transaction Info | Block #14512076/Trx ad9fd22a53eebccbb983e7fcd0e57b98b3ca629f |
View Raw JSON Data
{
"block": 14512076,
"op": [
"custom_json",
{
"id": "follow",
"json": "[\"reblog\",{\"account\":\"icostan\",\"author\":\"heimindanger\",\"permlink\":\"introducing-dtube-a-decentralized-video-platform-using-steem-and-ipfs\"}]",
"required_auths": [],
"required_posting_auths": [
"icostan"
]
}
],
"op_in_trx": 0,
"timestamp": "2017-08-12T14:11:21",
"trx_id": "ad9fd22a53eebccbb983e7fcd0e57b98b3ca629f",
"trx_in_block": 4,
"virtual_op": 0
}2017/08/12 14:08:39
2017/08/12 14:08:39
| author | heimindanger |
| permlink | introducing-dtube-a-decentralized-video-platform-using-steem-and-ipfs |
| voter | icostan |
| weight | 10000 (100.00%) |
| Transaction Info | Block #14512022/Trx 566b53ea9e464ef630369d9d08997ae6c5db9d10 |
View Raw JSON Data
{
"block": 14512022,
"op": [
"vote",
{
"author": "heimindanger",
"permlink": "introducing-dtube-a-decentralized-video-platform-using-steem-and-ipfs",
"voter": "icostan",
"weight": 10000
}
],
"op_in_trx": 0,
"timestamp": "2017-08-12T14:08:39",
"trx_id": "566b53ea9e464ef630369d9d08997ae6c5db9d10",
"trx_in_block": 2,
"virtual_op": 0
}Manabar
Voting Power100.00%
Downvote Power100.00%
Resource Credits100.00%
Reputation Progress0.00%
{
"voting_manabar": {
"current_mana": "8143659806",
"last_update_time": 1779067239
},
"downvote_manabar": {
"current_mana": 2035914951,
"last_update_time": 1779067239
},
"rc_account": {
"account": "icostan",
"rc_manabar": {
"current_mana": "10164408779",
"last_update_time": 1779067239
},
"max_rc_creation_adjustment": {
"amount": "2020748973",
"precision": 6,
"nai": "@@000000037"
},
"max_rc": "10164408779"
}
}Account Metadata
| POSTING JSON METADATA | |
| profile | {"name":"Iulian Costan","about":"Software developer, derivatives trader, crypto hodler.","website":"http://iuliancostan.com","location":"Romania","cover_image":"https://cdn.steemitimages.com/DQmRDebpsdxEV3eCyhwTw3yzSRVTmqU9nNP4WaxShFX3dmR/avatar-india.jpg","version":2} |
| JSON METADATA | |
| profile | {"name":"Iulian Costan","about":"Computer geek, derivatives trader, crypto hodler.","website":"http://iuliancostan.com","location":"Romania"} |
{
"posting_json_metadata": {
"profile": {
"name": "Iulian Costan",
"about": "Software developer, derivatives trader, crypto hodler.",
"website": "http://iuliancostan.com",
"location": "Romania",
"cover_image": "https://cdn.steemitimages.com/DQmRDebpsdxEV3eCyhwTw3yzSRVTmqU9nNP4WaxShFX3dmR/avatar-india.jpg",
"version": 2
}
},
"json_metadata": {
"profile": {
"name": "Iulian Costan",
"about": "Computer geek, derivatives trader, crypto hodler.",
"website": "http://iuliancostan.com",
"location": "Romania"
}
}
}Auth Keys
Owner
Single Signature
Public Keys
STM8khvozYSgQesA4HfUsz977WkPUnBJbUxoboqqkSdSURZcgowCq1/1
Active
Single Signature
Public Keys
STM7wXRVfSTGD8tos5uC444bf8FxeaZuXCmJjjSapRhEKBh2TbsQ31/1
Posting
Single Signature
Public Keys
STM6x1BPWfk5eFQg3cio62PoSkRYQCCzH99Eo3vXf68xVJSJ15zWB1/1
Memo
STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa
{
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM8khvozYSgQesA4HfUsz977WkPUnBJbUxoboqqkSdSURZcgowCq",
1
]
]
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM7wXRVfSTGD8tos5uC444bf8FxeaZuXCmJjjSapRhEKBh2TbsQ3",
1
]
]
},
"posting": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM6x1BPWfk5eFQg3cio62PoSkRYQCCzH99Eo3vXf68xVJSJ15zWB",
1
]
]
},
"memo": "STM6V2Sxgmf78xZgXczvitZXYQLZCq1ihi5xNCKej5KCiWoyWXQBa"
}Witness Votes
4 / 30
01.furion |
02.good-karma |
04.steemitboard |
[ "furion", "good-karma", "jerrybanfield", "steemitboard" ]