-
Notifications
You must be signed in to change notification settings - Fork 23
/
verifyIPFS.sol
127 lines (114 loc) · 4.09 KB
/
verifyIPFS.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
pragma solidity ^0.8.0;
/// @title verifyIPFS
/// @author Martin Lundfall (martin.lundfall@gmail.com)
library verifyIPFS {
bytes constant prefix1 = hex"0a";
bytes constant prefix2 = hex"080212";
bytes constant postfix = hex"18";
bytes constant sha256MultiHash = hex"1220";
bytes constant ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
/// @dev generates the corresponding IPFS hash (in base 58) to the given string
/// @param contentString The content of the IPFS object
/// @return The IPFS hash in base 58
function generateHash(string memory contentString) internal pure returns (bytes memory) {
bytes memory content = bytes(contentString);
bytes memory len = lengthEncode(content.length);
bytes memory len2 = lengthEncode(content.length + 4 + 2*len.length);
return toBase58(concat(sha256MultiHash, toBytes(sha256(abi.encodePacked(prefix1, len2, prefix2, len, content, postfix, len)))));
}
/// @dev Compares an IPFS hash with content
function verifyHash(string memory contentString, string memory hash) internal pure returns (bool) {
return equal(generateHash(contentString), bytes(hash));
}
/// @dev Converts hex string to base 58
function toBase58(bytes memory source) internal pure returns (bytes memory) {
if (source.length == 0) return new bytes(0);
uint8[] memory digits = new uint8[](64); //TODO: figure out exactly how much is needed
digits[0] = 0;
uint8 digitlength = 1;
for (uint256 i = 0; i<source.length; ++i) {
uint carry = uint8(source[i]);
for (uint256 j = 0; j<digitlength; ++j) {
carry += uint(digits[j]) * 256;
digits[j] = uint8(carry % 58);
carry = carry / 58;
}
while (carry > 0) {
digits[digitlength] = uint8(carry % 58);
digitlength++;
carry = carry / 58;
}
}
//return digits;
return toAlphabet(reverse(truncate(digits, digitlength)));
}
function lengthEncode(uint256 length) internal pure returns (bytes memory) {
if (length < 128) {
return to_binary(length);
}
else {
return concat(to_binary(length % 128 + 128), to_binary(length / 128));
}
}
function toBytes(bytes32 input) internal pure returns (bytes memory) {
bytes memory output = new bytes(32);
for (uint8 i = 0; i<32; i++) {
output[i] = input[i];
}
return output;
}
function equal(bytes memory one, bytes memory two) internal pure returns (bool) {
if (!(one.length == two.length)) {
return false;
}
for (uint256 i = 0; i<one.length; i++) {
if (!(one[i] == two[i])) {
return false;
}
}
return true;
}
function truncate(uint8[] memory array, uint8 length) internal pure returns (uint8[] memory) {
uint8[] memory output = new uint8[](length);
for (uint256 i = 0; i<length; i++) {
output[i] = array[i];
}
return output;
}
function reverse(uint8[] memory input) internal pure returns (uint8[] memory) {
uint8[] memory output = new uint8[](input.length);
for (uint256 i = 0; i<input.length; i++) {
output[i] = input[input.length-1-i];
}
return output;
}
function toAlphabet(uint8[] memory indices) internal pure returns (bytes memory) {
bytes memory output = new bytes(indices.length);
for (uint256 i = 0; i<indices.length; i++) {
output[i] = ALPHABET[indices[i]];
}
return output;
}
function concat(bytes memory byteArray, bytes memory byteArray2) internal pure returns (bytes memory) {
bytes memory returnArray = new bytes(byteArray.length + byteArray2.length);
uint i = 0;
for (i; i < byteArray.length; i++) {
returnArray[i] = byteArray[i];
}
for (i; i < (byteArray.length + byteArray2.length); i++) {
returnArray[i] = byteArray2[i - byteArray.length];
}
return returnArray;
}
function to_binary(uint256 x) internal pure returns (bytes memory) {
if (x == 0) {
return new bytes(0);
}
else {
bytes1 s = bytes1(uint8(x % 256));
bytes memory r = new bytes(1);
r[0] = s;
return concat(to_binary(x / 256), r);
}
}
}