mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-13 14:53:46 +00:00
Use sha1 instead of crc
This commit is contained in:
@@ -585,13 +585,11 @@ proc externalFileChanged(filename: string): bool =
|
||||
return false
|
||||
|
||||
var crcFile = toGeneratedFile(filename.withPackageName, "crc")
|
||||
var currentCrc = int(footprint(filename))
|
||||
var currentCrc = footprint(filename)
|
||||
var f: File
|
||||
if open(f, crcFile, fmRead):
|
||||
var line = newStringOfCap(40)
|
||||
if not f.readLine(line): line = "0"
|
||||
let oldCrc = parseSecureHash(f.readLine())
|
||||
close(f)
|
||||
var oldCrc = parseInt(line)
|
||||
result = oldCrc != currentCrc
|
||||
else:
|
||||
result = true
|
||||
|
||||
@@ -541,7 +541,8 @@ proc cmdChangeTriggersRecompilation(old, new: TCommands): bool =
|
||||
proc processRodFile(r: PRodReader, crc: SecureHash) =
|
||||
var
|
||||
w: string
|
||||
d, inclCrc: int
|
||||
d: int
|
||||
var inclCrc: SecureHash
|
||||
while r.s[r.pos] != '\0':
|
||||
var section = rdWord(r)
|
||||
if r.reason != rrNone:
|
||||
@@ -549,7 +550,8 @@ proc processRodFile(r: PRodReader, crc: SecureHash) =
|
||||
case section
|
||||
of "CRC":
|
||||
inc(r.pos) # skip ':'
|
||||
if int(crc) != decodeVInt(r.s, r.pos): r.reason = rrCrcChange
|
||||
if crc != parseSecureHash(decodeStr(r.s, r.pos)):
|
||||
r.reason = rrCrcChange
|
||||
of "ID":
|
||||
inc(r.pos) # skip ':'
|
||||
r.moduleID = decodeVInt(r.s, r.pos)
|
||||
@@ -596,9 +598,9 @@ proc processRodFile(r: PRodReader, crc: SecureHash) =
|
||||
while r.s[r.pos] != ')':
|
||||
w = r.files[decodeVInt(r.s, r.pos)].toFullPath
|
||||
inc(r.pos) # skip ' '
|
||||
inclCrc = decodeVInt(r.s, r.pos)
|
||||
inclCrc = parseSecureHash(decodeStr(r.s, r.pos))
|
||||
if r.reason == rrNone:
|
||||
if not existsFile(w) or (inclCrc != int(secureHashFile(w))):
|
||||
if not existsFile(w) or (inclCrc != secureHashFile(w)):
|
||||
r.reason = rrInclDeps
|
||||
if r.s[r.pos] == '\x0A':
|
||||
inc(r.pos)
|
||||
@@ -649,7 +651,7 @@ proc startsWith(buf: cstring, token: string, pos = 0): bool =
|
||||
while s < token.len and buf[pos+s] == token[s]: inc s
|
||||
result = s == token.len
|
||||
|
||||
proc newRodReader(modfilename: string, crc: SecureHash,
|
||||
proc newRodReader(modfilename: string, crc: SecureHash,
|
||||
readerIndex: int): PRodReader =
|
||||
new(result)
|
||||
try:
|
||||
@@ -1017,7 +1019,7 @@ proc writeType(f: File; t: PType) =
|
||||
f.write("]\n")
|
||||
|
||||
proc viewFile(rodfile: string) =
|
||||
var r = newRodReader(rodfile, 0, 0)
|
||||
var r = newRodReader(rodfile, secureHash(""), 0)
|
||||
if r == nil:
|
||||
rawMessage(errGenerated, "cannot open file (or maybe wrong version):" &
|
||||
rodfile)
|
||||
|
||||
@@ -96,7 +96,7 @@ proc addInclDep(w: PRodWriter, dep: string) =
|
||||
var resolved = dep.findModule(w.module.info.toFullPath)
|
||||
encodeVInt(fileIdx(w, dep), w.inclDeps)
|
||||
add(w.inclDeps, " ")
|
||||
encodeVInt(secureHashFile(resolved), w.inclDeps)
|
||||
encodeStr($secureHashFile(resolved), w.inclDeps)
|
||||
add(w.inclDeps, rodNL)
|
||||
|
||||
proc pushType(w: PRodWriter, t: PType) =
|
||||
@@ -440,7 +440,7 @@ proc writeRod(w: PRodWriter) =
|
||||
f.write(rodNL)
|
||||
|
||||
var crc = "CRC:"
|
||||
encodeVInt(w.crc, crc)
|
||||
encodeStr($w.crc, crc)
|
||||
f.write(crc)
|
||||
f.write(rodNL)
|
||||
|
||||
|
||||
@@ -1,101 +1,202 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2015 Nim Contributers
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
import
|
||||
strutils
|
||||
import
|
||||
strutils, unsigned
|
||||
|
||||
type
|
||||
SecureHash* = int32
|
||||
const sha_digest_size = 20
|
||||
|
||||
const
|
||||
InitCrc32 = SecureHash(- 1)
|
||||
type
|
||||
SHA1Digest = array[0 .. sha_digest_size-1, uint8]
|
||||
SecureHash* = distinct SHA1Digest
|
||||
|
||||
proc secureHashFile*(filename: string): SecureHash
|
||||
# implementation
|
||||
const emptySecureHash = SecureHash([
|
||||
0u8, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
])
|
||||
|
||||
type
|
||||
TCRC_TabEntry = int
|
||||
proc sha1(src: string) : SHA1Digest
|
||||
|
||||
const
|
||||
crc32table: array[0..255, TCRC_TabEntry] = [0, 1996959894, - 301047508,
|
||||
- 1727442502, 124634137, 1886057615, - 379345611, - 1637575261, 249268274,
|
||||
2044508324, - 522852066, - 1747789432, 162941995, 2125561021, - 407360249,
|
||||
- 1866523247, 498536548, 1789927666, - 205950648, - 2067906082, 450548861,
|
||||
1843258603, - 187386543, - 2083289657, 325883990, 1684777152, - 43845254,
|
||||
- 1973040660, 335633487, 1661365465, - 99664541, - 1928851979, 997073096,
|
||||
1281953886, - 715111964, - 1570279054, 1006888145, 1258607687, - 770865667,
|
||||
- 1526024853, 901097722, 1119000684, - 608450090, - 1396901568, 853044451,
|
||||
1172266101, - 589951537, - 1412350631, 651767980, 1373503546, - 925412992,
|
||||
- 1076862698, 565507253, 1454621731, - 809855591, - 1195530993, 671266974,
|
||||
1594198024, - 972236366, - 1324619484, 795835527, 1483230225, - 1050600021,
|
||||
- 1234817731, 1994146192, 31158534, - 1731059524, - 271249366, 1907459465,
|
||||
112637215, - 1614814043, - 390540237, 2013776290, 251722036, - 1777751922,
|
||||
- 519137256, 2137656763, 141376813, - 1855689577, - 429695999, 1802195444,
|
||||
476864866, - 2056965928, - 228458418, 1812370925, 453092731, - 2113342271,
|
||||
- 183516073, 1706088902, 314042704, - 1950435094, - 54949764, 1658658271,
|
||||
366619977, - 1932296973, - 69972891, 1303535960, 984961486, - 1547960204,
|
||||
- 725929758, 1256170817, 1037604311, - 1529756563, - 740887301, 1131014506,
|
||||
879679996, - 1385723834, - 631195440, 1141124467, 855842277, - 1442165665,
|
||||
- 586318647, 1342533948, 654459306, - 1106571248, - 921952122, 1466479909,
|
||||
544179635, - 1184443383, - 832445281, 1591671054, 702138776, - 1328506846,
|
||||
- 942167884, 1504918807, 783551873, - 1212326853, - 1061524307, - 306674912,
|
||||
- 1698712650, 62317068, 1957810842, - 355121351, - 1647151185, 81470997,
|
||||
1943803523, - 480048366, - 1805370492, 225274430, 2053790376, - 468791541,
|
||||
- 1828061283, 167816743, 2097651377, - 267414716, - 2029476910, 503444072,
|
||||
1762050814, - 144550051, - 2140837941, 426522225, 1852507879, - 19653770,
|
||||
- 1982649376, 282753626, 1742555852, - 105259153, - 1900089351, 397917763,
|
||||
1622183637, - 690576408, - 1580100738, 953729732, 1340076626, - 776247311,
|
||||
- 1497606297, 1068828381, 1219638859, - 670225446, - 1358292148, 906185462,
|
||||
1090812512, - 547295293, - 1469587627, 829329135, 1181335161, - 882789492,
|
||||
- 1134132454, 628085408, 1382605366, - 871598187, - 1156888829, 570562233,
|
||||
1426400815, - 977650754, - 1296233688, 733239954, 1555261956, - 1026031705,
|
||||
- 1244606671, 752459403, 1541320221, - 1687895376, - 328994266, 1969922972,
|
||||
40735498, - 1677130071, - 351390145, 1913087877, 83908371, - 1782625662,
|
||||
- 491226604, 2075208622, 213261112, - 1831694693, - 438977011, 2094854071,
|
||||
198958881, - 2032938284, - 237706686, 1759359992, 534414190, - 2118248755,
|
||||
- 155638181, 1873836001, 414664567, - 2012718362, - 15766928, 1711684554,
|
||||
285281116, - 1889165569, - 127750551, 1634467795, 376229701, - 1609899400,
|
||||
- 686959890, 1308918612, 956543938, - 1486412191, - 799009033, 1231636301,
|
||||
1047427035, - 1362007478, - 640263460, 1088359270, 936918000, - 1447252397,
|
||||
- 558129467, 1202900863, 817233897, - 1111625188, - 893730166, 1404277552,
|
||||
615818150, - 1160759803, - 841546093, 1423857449, 601450431, - 1285129682,
|
||||
- 1000256840, 1567103746, 711928724, - 1274298825, - 1022587231, 1510334235,
|
||||
755167117]
|
||||
proc secureHash*(str: string): SecureHash = SecureHash(sha1(str))
|
||||
proc secureHashFile*(filename: string): SecureHash = secureHash(readFile(filename))
|
||||
proc `$`*(self: SecureHash): string =
|
||||
result = ""
|
||||
for v in SHA1Digest(self):
|
||||
result.add(toHex(int(v), 2))
|
||||
|
||||
proc updateCrc32(val: int8, crc: SecureHash): SecureHash =
|
||||
result = SecureHash(crc32table[(int(crc) xor (int(val) and 0x000000FF)) and
|
||||
0x000000FF]) xor (crc shr SecureHash(8))
|
||||
proc parseSecureHash*(hash: string): SecureHash =
|
||||
for i in 0.. <sha_digest_size:
|
||||
SHA1Digest(result)[i] = uint8(parseHexInt(hash[i*2] & hash[i*2 + 1]))
|
||||
|
||||
proc updateCrc32(val: char, crc: SecureHash): SecureHash =
|
||||
result = updateCrc32(toU8(ord(val)), crc)
|
||||
proc `==`*(a, b: SecureHash): bool =
|
||||
# Not a constant-time comparison, but that's acceptable in this context
|
||||
SHA1Digest(a) == SHA1Digest(b)
|
||||
|
||||
proc secureHash*(s: string): SecureHash =
|
||||
result = InitCrc32
|
||||
for i in 0..len(s)-1: result = updateCrc32(s[i], result)
|
||||
|
||||
type
|
||||
TByteArray = array[0..10000000, int8]
|
||||
PByteArray = ref TByteArray
|
||||
|
||||
proc secureHashFile(filename: string): SecureHash =
|
||||
const
|
||||
bufSize = 8000 # don't use 8K for the memory allocator!
|
||||
var
|
||||
bin: File
|
||||
result = InitCrc32
|
||||
if not open(bin, filename):
|
||||
return # not equal if file does not exist
|
||||
var buf = alloc(bufSize)
|
||||
var p = cast[PByteArray](buf)
|
||||
while true:
|
||||
var readBytes = readBuffer(bin, buf, bufSize)
|
||||
for i in countup(0, readBytes - 1): result = updateCrc32(p[i], result)
|
||||
if readBytes != bufSize: break
|
||||
dealloc(buf)
|
||||
close(bin)
|
||||
|
||||
# Copyright (c) 2011, Micael Hildenborg
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Micael Hildenborg nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Ported to Nim by Erik O'Leary
|
||||
|
||||
type
|
||||
SHA1State = array[0 .. 5-1, uint32]
|
||||
SHA1Buffer = array[0 .. 80-1, uint32]
|
||||
|
||||
template clearBuffer(w: SHA1Buffer, len = 16) =
|
||||
zeroMem(addr(w), len * sizeof(uint32))
|
||||
|
||||
proc init(result: var SHA1State) =
|
||||
result[0] = 0x67452301'u32
|
||||
result[1] = 0xefcdab89'u32
|
||||
result[2] = 0x98badcfe'u32
|
||||
result[3] = 0x10325476'u32
|
||||
result[4] = 0xc3d2e1f0'u32
|
||||
|
||||
proc innerHash(state: var SHA1State, w: var SHA1Buffer) =
|
||||
var
|
||||
a = state[0]
|
||||
b = state[1]
|
||||
c = state[2]
|
||||
d = state[3]
|
||||
e = state[4]
|
||||
|
||||
var round = 0
|
||||
|
||||
template rot(value, bits: uint32): uint32 {.immediate.} =
|
||||
(value shl bits) or (value shr (32 - bits))
|
||||
|
||||
template sha1(fun, val: uint32): stmt =
|
||||
let t = rot(a, 5) + fun + e + val + w[round]
|
||||
e = d
|
||||
d = c
|
||||
c = rot(b, 30)
|
||||
b = a
|
||||
a = t
|
||||
|
||||
template process(body: stmt): stmt =
|
||||
w[round] = rot(w[round - 3] xor w[round - 8] xor w[round - 14] xor w[round - 16], 1)
|
||||
body
|
||||
inc(round)
|
||||
|
||||
template wrap(dest, value: expr): stmt {.immediate.} =
|
||||
let v = dest + value
|
||||
dest = v
|
||||
|
||||
while round < 16:
|
||||
sha1((b and c) or (not b and d), 0x5a827999'u32)
|
||||
inc(round)
|
||||
|
||||
while round < 20:
|
||||
process:
|
||||
sha1((b and c) or (not b and d), 0x5a827999'u32)
|
||||
|
||||
while round < 40:
|
||||
process:
|
||||
sha1(b xor c xor d, 0x6ed9eba1'u32)
|
||||
|
||||
while round < 60:
|
||||
process:
|
||||
sha1((b and c) or (b and d) or (c and d), 0x8f1bbcdc'u32)
|
||||
|
||||
while round < 80:
|
||||
process:
|
||||
sha1(b xor c xor d, 0xca62c1d6'u32)
|
||||
|
||||
wrap state[0], a
|
||||
wrap state[1], b
|
||||
wrap state[2], c
|
||||
wrap state[3], d
|
||||
wrap state[4], e
|
||||
|
||||
template computeInternal(src: expr): stmt {.immediate.} =
|
||||
#Initialize state
|
||||
var state: SHA1State
|
||||
init(state)
|
||||
|
||||
#Create w buffer
|
||||
var w: SHA1Buffer
|
||||
|
||||
#Loop through all complete 64byte blocks.
|
||||
let byteLen = src.len
|
||||
let endOfFullBlocks = byteLen - 64
|
||||
var endCurrentBlock = 0
|
||||
var currentBlock = 0
|
||||
|
||||
while currentBlock <= endOfFullBlocks:
|
||||
endCurrentBlock = currentBlock + 64
|
||||
|
||||
var i = 0
|
||||
while currentBlock < endCurrentBlock:
|
||||
w[i] = uint32(src[currentBlock+3]) or
|
||||
uint32(src[currentBlock+2]) shl 8'u32 or
|
||||
uint32(src[currentBlock+1]) shl 16'u32 or
|
||||
uint32(src[currentBlock]) shl 24'u32
|
||||
currentBlock += 4
|
||||
inc(i)
|
||||
|
||||
innerHash(state, w)
|
||||
|
||||
#Handle last and not full 64 byte block if existing
|
||||
endCurrentBlock = byteLen - currentBlock
|
||||
clearBuffer(w)
|
||||
var lastBlockBytes = 0
|
||||
|
||||
while lastBlockBytes < endCurrentBlock:
|
||||
|
||||
var value = uint32(src[lastBlockBytes + currentBlock]) shl
|
||||
((3'u32 - (lastBlockBytes and 3)) shl 3)
|
||||
|
||||
w[lastBlockBytes shr 2] = w[lastBlockBytes shr 2] or value
|
||||
inc(lastBlockBytes)
|
||||
|
||||
w[lastBlockBytes shr 2] = w[lastBlockBytes shr 2] or (
|
||||
0x80'u32 shl ((3'u32 - (lastBlockBytes and 3)) shl 3)
|
||||
)
|
||||
|
||||
if endCurrentBlock >= 56:
|
||||
innerHash(state, w)
|
||||
clearBuffer(w)
|
||||
|
||||
w[15] = uint32(byteLen) shl 3
|
||||
innerHash(state, w)
|
||||
|
||||
# Store hash in result pointer, and make sure we get in in the correct order
|
||||
# on both endian models.
|
||||
for i in 0 .. sha_digest_size-1:
|
||||
result[i] = uint8((int(state[i shr 2]) shr ((3-(i and 3)) * 8)) and 255)
|
||||
|
||||
proc sha1(src: string) : SHA1Digest =
|
||||
## Calculate SHA1 from input string
|
||||
computeInternal(src)
|
||||
|
||||
Reference in New Issue
Block a user