Split argon2 / blake2b code, use go 1.21 features
This commit is contained in:
parent
5e7d8ea35f
commit
2c713700c1
58
argon2.go
Normal file
58
argon2.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
package randomx
|
||||
|
||||
import "golang.org/x/crypto/blake2b"
|
||||
|
||||
import (
|
||||
_ "golang.org/x/crypto/argon2"
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
// see reference configuration.h
|
||||
// Cache size in KiB. Must be a power of 2.
|
||||
const RANDOMX_ARGON_MEMORY = 262144
|
||||
|
||||
// Number of Argon2d iterations for Cache initialization.
|
||||
const RANDOMX_ARGON_ITERATIONS = 3
|
||||
|
||||
// Number of parallel lanes for Cache initialization.
|
||||
const RANDOMX_ARGON_LANES = 1
|
||||
|
||||
// Argon2d salt
|
||||
const RANDOMX_ARGON_SALT = "RandomX\x03"
|
||||
const ArgonSaltSize uint32 = 8 //sizeof("" RANDOMX_ARGON_SALT) - 1
|
||||
|
||||
const ArgonBlockSize uint32 = 1024
|
||||
|
||||
type argonBlock [128]uint64
|
||||
|
||||
const syncPoints = 4
|
||||
|
||||
//go:linkname argon2_initHash golang.org/x/crypto/argon2.initHash
|
||||
func argon2_initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte
|
||||
|
||||
//go:linkname argon2_initBlocks golang.org/x/crypto/argon2.initBlocks
|
||||
func argon2_initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []argonBlock
|
||||
|
||||
//go:linkname argon2_processBlocks golang.org/x/crypto/argon2.processBlocks
|
||||
func argon2_processBlocks(B []argonBlock, time, memory, threads uint32, mode int)
|
||||
|
||||
// argon2_buildBlocks From golang.org/x/crypto/argon2.deriveKey without last deriveKey call
|
||||
func argon2_buildBlocks(password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []argonBlock {
|
||||
if time < 1 {
|
||||
panic("argon2: number of rounds too small")
|
||||
}
|
||||
if threads < 1 {
|
||||
panic("argon2: parallelism degree too low")
|
||||
}
|
||||
const mode = 0 /* argon2d */
|
||||
h0 := argon2_initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode)
|
||||
|
||||
memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads))
|
||||
if memory < 2*syncPoints*uint32(threads) {
|
||||
memory = 2 * syncPoints * uint32(threads)
|
||||
}
|
||||
B := argon2_initBlocks(&h0, memory, uint32(threads))
|
||||
argon2_processBlocks(B, time, memory, uint32(threads), mode)
|
||||
|
||||
return B
|
||||
}
|
51
blake2b.go
Normal file
51
blake2b.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package randomx
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"golang.org/x/crypto/blake2b"
|
||||
)
|
||||
|
||||
type Blake2Generator struct {
|
||||
data [64]byte
|
||||
dataindex int
|
||||
allocRegIndex [8]int
|
||||
allocRegisters [8]Register
|
||||
}
|
||||
|
||||
func Init_Blake2Generator(key []byte, nonce uint32) *Blake2Generator {
|
||||
var b Blake2Generator
|
||||
b.dataindex = len(b.data)
|
||||
if len(key) > 60 {
|
||||
copy(b.data[:], key[0:60])
|
||||
} else {
|
||||
copy(b.data[:], key)
|
||||
}
|
||||
binary.LittleEndian.PutUint32(b.data[60:], nonce)
|
||||
|
||||
return &b
|
||||
}
|
||||
|
||||
func (b *Blake2Generator) checkdata(bytesNeeded int) {
|
||||
if b.dataindex+bytesNeeded > cap(b.data) {
|
||||
//blake2b(data, sizeof(data), data, sizeof(data), nullptr, 0);
|
||||
h := blake2b.Sum512(b.data[:])
|
||||
copy(b.data[:], h[:])
|
||||
b.dataindex = 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (b *Blake2Generator) GetByte() byte {
|
||||
b.checkdata(1)
|
||||
ret := b.data[b.dataindex]
|
||||
//fmt.Printf("returning byte %02x\n", ret)
|
||||
b.dataindex++
|
||||
return ret
|
||||
}
|
||||
func (b *Blake2Generator) GetUint32() uint32 {
|
||||
b.checkdata(4)
|
||||
ret := binary.LittleEndian.Uint32(b.data[b.dataindex:])
|
||||
b.dataindex += 4
|
||||
|
||||
return ret
|
||||
}
|
45
cache.go
45
cache.go
|
@ -1,7 +1,19 @@
|
|||
package randomx
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type MemoryBlock [128]uint64
|
||||
|
||||
func (m MemoryBlock) getLine(addr uint64) []uint64 {
|
||||
addr >>= 3
|
||||
return m[addr : addr+8]
|
||||
}
|
||||
|
||||
type Randomx_Cache struct {
|
||||
Blocks []block
|
||||
Blocks []MemoryBlock
|
||||
|
||||
Programs [RANDOMX_PROGRAM_COUNT]*SuperScalarProgram
|
||||
}
|
||||
|
@ -19,16 +31,19 @@ func (cache *Randomx_Cache) VM_Initialize() *VM {
|
|||
}
|
||||
}
|
||||
|
||||
func (cache *Randomx_Cache) Randomx_init_cache(key []byte) {
|
||||
func (cache *Randomx_Cache) Init(key []byte) {
|
||||
//fmt.Printf("appending null byte is not necessary but only done for testing")
|
||||
kkey := append([]byte{}, key...)
|
||||
//kkey = append(kkey,0)
|
||||
//cache->initialize(cache, key, keySize);
|
||||
cache.Blocks = buildBlocks(argon2d, kkey, []byte(RANDOMX_ARGON_SALT), []byte{}, []byte{}, RANDOMX_ARGON_ITERATIONS, RANDOMX_ARGON_MEMORY, RANDOMX_ARGON_LANES, 0)
|
||||
argonBlocks := argon2_buildBlocks(kkey, []byte(RANDOMX_ARGON_SALT), []byte{}, []byte{}, RANDOMX_ARGON_ITERATIONS, RANDOMX_ARGON_MEMORY, RANDOMX_ARGON_LANES, 0)
|
||||
|
||||
memoryBlocks := unsafe.Slice((*MemoryBlock)(unsafe.Pointer(unsafe.SliceData(argonBlocks))), int(unsafe.Sizeof(argonBlock{}))/int(unsafe.Sizeof(MemoryBlock{}))*len(argonBlocks))
|
||||
|
||||
cache.Blocks = slices.Clone(memoryBlocks)
|
||||
}
|
||||
|
||||
// fetch a 64 byte block in uint64 form
|
||||
// GetMixBlock fetch a 64 byte block in uint64 form
|
||||
func (cache *Randomx_Cache) GetMixBlock(addr uint64) []uint64 {
|
||||
|
||||
mask := CacheSize/CacheLineSize - 1
|
||||
|
@ -36,12 +51,10 @@ func (cache *Randomx_Cache) GetMixBlock(addr uint64) []uint64 {
|
|||
addr = (addr & mask) * CacheLineSize
|
||||
|
||||
block := addr / 1024
|
||||
index_within_block := (addr % 1024) / 8
|
||||
|
||||
return cache.Blocks[block][index_within_block : index_within_block+8]
|
||||
return cache.Blocks[block].getLine(addr % 1024)
|
||||
}
|
||||
|
||||
func (cache *Randomx_Cache) InitDatasetItem(out *registerLine, itemnumber uint64) {
|
||||
func (cache *Randomx_Cache) InitDatasetItem(out *registerLine, itemNumber uint64) {
|
||||
const superscalarMul0 uint64 = 6364136223846793005
|
||||
const superscalarAdd1 uint64 = 9298411001130361340
|
||||
const superscalarAdd2 uint64 = 12065312585734608966
|
||||
|
@ -53,10 +66,10 @@ func (cache *Randomx_Cache) InitDatasetItem(out *registerLine, itemnumber uint64
|
|||
|
||||
var rl registerLine
|
||||
|
||||
register_value := itemnumber
|
||||
register_value := itemNumber
|
||||
_ = register_value
|
||||
|
||||
rl[0] = (itemnumber + 1) * superscalarMul0
|
||||
rl[0] = (itemNumber + 1) * superscalarMul0
|
||||
rl[1] = rl[0] ^ superscalarAdd1
|
||||
rl[2] = rl[0] ^ superscalarAdd2
|
||||
rl[3] = rl[0] ^ superscalarAdd3
|
||||
|
@ -85,14 +98,8 @@ func (cache *Randomx_Cache) InitDatasetItem(out *registerLine, itemnumber uint64
|
|||
}
|
||||
}
|
||||
|
||||
func (cache *Randomx_Cache) initDataset(start_item, end_item uint64) {
|
||||
for itemnumber := start_item; itemnumber < end_item; itemnumber++ {
|
||||
|
||||
cache.InitDatasetItem(nil, itemnumber)
|
||||
|
||||
// dataset_index += CacheLineSize
|
||||
//fmt.Printf("exiting dataset item\n")
|
||||
break
|
||||
|
||||
func (cache *Randomx_Cache) initDataset(dataset []registerLine, startItem, endItem uint64) {
|
||||
for itemNumber := startItem; itemNumber < endItem; itemNumber, dataset = itemNumber+1, dataset[1:] {
|
||||
cache.InitDatasetItem(&dataset[0], itemNumber)
|
||||
}
|
||||
}
|
||||
|
|
112
config.go
112
config.go
|
@ -29,26 +29,6 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
package randomx
|
||||
|
||||
import "encoding/binary"
|
||||
import "golang.org/x/crypto/blake2b"
|
||||
|
||||
import _ "unsafe"
|
||||
import _ "golang.org/x/crypto/argon2"
|
||||
|
||||
// see reference configuration.h
|
||||
// Cache size in KiB. Must be a power of 2.
|
||||
const RANDOMX_ARGON_MEMORY = 262144
|
||||
|
||||
// Number of Argon2d iterations for Cache initialization.
|
||||
const RANDOMX_ARGON_ITERATIONS = 3
|
||||
|
||||
// Number of parallel lanes for Cache initialization.
|
||||
const RANDOMX_ARGON_LANES = 1
|
||||
|
||||
// Argon2d salt
|
||||
const RANDOMX_ARGON_SALT = "RandomX\x03"
|
||||
const ArgonSaltSize uint32 = 8 //sizeof("" RANDOMX_ARGON_SALT) - 1;
|
||||
|
||||
// Number of random Cache accesses per Dataset item. Minimum is 2.
|
||||
const RANDOMX_CACHE_ACCESSES = 8
|
||||
|
||||
|
@ -87,7 +67,6 @@ const RANDOMX_JUMP_OFFSET = 8
|
|||
|
||||
const DATASETEXTRAITEMS = RANDOMX_DATASET_EXTRA_SIZE / RANDOMX_DATASET_ITEM_SIZE
|
||||
|
||||
const ArgonBlockSize uint32 = 1024
|
||||
const SuperscalarMaxSize int = 3*RANDOMX_SUPERSCALAR_LATENCY + 2
|
||||
const RANDOMX_DATASET_ITEM_SIZE uint64 = 64
|
||||
const CacheLineSize uint64 = RANDOMX_DATASET_ITEM_SIZE
|
||||
|
@ -130,94 +109,3 @@ const RANDOMX_FLAG_LARGE_PAGES = 2
|
|||
func isZeroOrPowerOf2(x uint32) bool {
|
||||
return (x & (x - 1)) == 0
|
||||
}
|
||||
|
||||
type Blake2Generator struct {
|
||||
data [64]byte
|
||||
dataindex int
|
||||
allocRegIndex [8]int
|
||||
allocRegisters [8]Register
|
||||
}
|
||||
|
||||
func Init_Blake2Generator(key []byte, nonce uint32) *Blake2Generator {
|
||||
var b Blake2Generator
|
||||
b.dataindex = len(b.data)
|
||||
if len(key) > 60 {
|
||||
copy(b.data[:], key[0:60])
|
||||
} else {
|
||||
copy(b.data[:], key)
|
||||
}
|
||||
binary.LittleEndian.PutUint32(b.data[60:], nonce)
|
||||
|
||||
return &b
|
||||
}
|
||||
|
||||
func (b *Blake2Generator) checkdata(bytesNeeded int) {
|
||||
if b.dataindex+bytesNeeded > cap(b.data) {
|
||||
//blake2b(data, sizeof(data), data, sizeof(data), nullptr, 0);
|
||||
h := blake2b.Sum512(b.data[:])
|
||||
copy(b.data[:], h[:])
|
||||
b.dataindex = 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (b *Blake2Generator) GetByte() byte {
|
||||
b.checkdata(1)
|
||||
ret := b.data[b.dataindex]
|
||||
//fmt.Printf("returning byte %02x\n", ret)
|
||||
b.dataindex++
|
||||
return ret
|
||||
}
|
||||
func (b *Blake2Generator) GetUint32() uint32 {
|
||||
b.checkdata(4)
|
||||
ret := uint32(binary.LittleEndian.Uint32(b.data[b.dataindex:]))
|
||||
//fmt.Printf("returning int32 %08x %08x\n", ret, binary.LittleEndian.Uint32(b.data[b.dataindex:]))
|
||||
b.dataindex += 4
|
||||
//fmt.Printf("returning int32 %08x\n", ret)
|
||||
|
||||
if ret == 0xc5dac17e {
|
||||
// panic("exiting")
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// some constants for argon
|
||||
const (
|
||||
argon2d = iota
|
||||
argon2i
|
||||
argon2id
|
||||
)
|
||||
|
||||
type block [128]uint64
|
||||
|
||||
const syncPoints = 4
|
||||
|
||||
//go:linkname argon2_initHash golang.org/x/crypto/argon2.initHash
|
||||
func argon2_initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte
|
||||
|
||||
//go:linkname argon2_initBlocks golang.org/x/crypto/argon2.initBlocks
|
||||
func argon2_initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block
|
||||
|
||||
//go:linkname argon2_processBlocks golang.org/x/crypto/argon2.processBlocks
|
||||
func argon2_processBlocks(B []block, time, memory, threads uint32, mode int)
|
||||
|
||||
func buildBlocks(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []block {
|
||||
if time < 1 {
|
||||
panic("argon2: number of rounds too small")
|
||||
}
|
||||
if threads < 1 {
|
||||
panic("argon2: parallelism degree too low")
|
||||
}
|
||||
h0 := argon2_initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode)
|
||||
|
||||
memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads))
|
||||
if memory < 2*syncPoints*uint32(threads) {
|
||||
memory = 2 * syncPoints * uint32(threads)
|
||||
}
|
||||
B := argon2_initBlocks(&h0, memory, uint32(threads))
|
||||
argon2_processBlocks(B, time, memory, uint32(threads), mode)
|
||||
|
||||
return B
|
||||
//return extractKey(B, memory, uint32(threads), keyLen)
|
||||
}
|
||||
|
|
|
@ -9,11 +9,9 @@ func (d *Randomx_DatasetLight) PrefetchDataset(address uint64) {
|
|||
}
|
||||
|
||||
func (d *Randomx_DatasetLight) ReadDataset(address uint64, r *registerLine) {
|
||||
itemnumber := address / CacheLineSize
|
||||
|
||||
var out registerLine
|
||||
|
||||
d.Cache.InitDatasetItem(&out, itemnumber)
|
||||
d.Cache.InitDatasetItem(&out, address/CacheLineSize)
|
||||
|
||||
for i := range r {
|
||||
r[i] ^= out[i]
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1,6 +1,6 @@
|
|||
module git.gammaspectra.live/P2Pool/go-randomx
|
||||
|
||||
go 1.17
|
||||
go 1.21
|
||||
|
||||
require golang.org/x/crypto v0.22.0
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ func Test_Randomx(t *testing.T) {
|
|||
for ix, tt := range Tests {
|
||||
|
||||
t.Run(string(tt.key)+"_____"+string(tt.input), func(t *testing.T) {
|
||||
c.Randomx_init_cache(tt.key)
|
||||
c.Init(tt.key)
|
||||
|
||||
nonce := uint32(0) //uint32(len(key))
|
||||
gen := Init_Blake2Generator(tt.key, nonce)
|
||||
|
@ -82,7 +82,7 @@ func Benchmark_RandomX(b *testing.B) {
|
|||
|
||||
c := Randomx_alloc_cache(0)
|
||||
|
||||
c.Randomx_init_cache(tt.key)
|
||||
c.Init(tt.key)
|
||||
|
||||
nonce := uint32(0) //uint32(len(key))
|
||||
gen := Init_Blake2Generator(tt.key, nonce)
|
||||
|
|
Loading…
Reference in a new issue