2019-02-25 22:44:14 +00:00
package hash
import (
"crypto/sha256"
2021-03-25 12:22:16 +00:00
"encoding/binary"
2019-02-25 22:44:14 +00:00
2020-03-03 14:21:42 +00:00
"github.com/nspcc-dev/neo-go/pkg/util"
2021-05-12 19:52:32 +00:00
"golang.org/x/crypto/ripemd160" //nolint:staticcheck // SA1019: package golang.org/x/crypto/ripemd160 is deprecated
2024-05-01 12:44:14 +00:00
"golang.org/x/crypto/sha3"
2019-02-25 22:44:14 +00:00
)
2022-04-20 18:30:09 +00:00
// Hashable represents an object which can be hashed. Usually, these objects
2021-03-25 12:22:16 +00:00
// are io.Serializable and signable. They tend to cache the hash inside for
// effectiveness, providing this accessor method. Anything that can be
// identified with a hash can then be signed and verified.
type Hashable interface {
Hash ( ) util . Uint256
}
2024-05-02 11:06:37 +00:00
// GetSignedData returns the concatenated byte slice containing of the network
// magic in constant-length 4-bytes LE representation and hashable item hash in BE
// representation.
func GetSignedData ( net uint32 , hh Hashable ) [ ] byte {
2022-10-05 07:45:52 +00:00
var b = make ( [ ] byte , 4 + util . Uint256Size )
2021-03-25 12:22:16 +00:00
binary . LittleEndian . PutUint32 ( b , net )
h := hh . Hash ( )
copy ( b [ 4 : ] , h [ : ] )
return b
}
2022-04-20 18:30:09 +00:00
// NetSha256 calculates a network-specific hash of the Hashable item that can then
2021-03-25 12:22:16 +00:00
// be signed/verified.
func NetSha256 ( net uint32 , hh Hashable ) util . Uint256 {
2024-05-02 11:06:37 +00:00
return Sha256 ( GetSignedData ( net , hh ) )
2021-03-25 12:22:16 +00:00
}
2019-03-17 18:26:35 +00:00
// Sha256 hashes the incoming byte slice
2019-10-22 14:56:03 +00:00
// using the sha256 algorithm.
2019-08-23 14:08:19 +00:00
func Sha256 ( data [ ] byte ) util . Uint256 {
hash := sha256 . Sum256 ( data )
return hash
2019-02-25 22:44:14 +00:00
}
2019-10-22 14:56:03 +00:00
// DoubleSha256 performs sha256 twice on the given data.
2019-08-23 14:08:19 +00:00
func DoubleSha256 ( data [ ] byte ) util . Uint256 {
2019-02-25 22:44:14 +00:00
var hash util . Uint256
2019-08-23 14:08:19 +00:00
h1 := Sha256 ( data )
2019-11-27 09:23:18 +00:00
hash = Sha256 ( h1 . BytesBE ( ) )
2019-08-23 14:08:19 +00:00
return hash
2019-02-25 22:44:14 +00:00
}
2024-05-01 12:44:14 +00:00
// Keccak256 hashes the incoming byte slice using the
// keccak256 algorithm.
func Keccak256 ( data [ ] byte ) util . Uint256 {
var hash util . Uint256
hasher := sha3 . NewLegacyKeccak256 ( ) // TODO: @roman-khimov, can we allow to replace it with New256? I don't think we ever need non-standard padding support.
_ , _ = hasher . Write ( data )
hasher . Sum ( hash [ : 0 ] )
return hash
}
2019-03-17 18:26:35 +00:00
// RipeMD160 performs the RIPEMD160 hash algorithm
2019-10-22 14:56:03 +00:00
// on the given data.
2019-08-23 14:23:11 +00:00
func RipeMD160 ( data [ ] byte ) util . Uint160 {
2019-02-25 22:44:14 +00:00
var hash util . Uint160
hasher := ripemd160 . New ( )
2019-08-23 14:23:11 +00:00
_ , _ = hasher . Write ( data )
2021-12-02 13:11:09 +00:00
hasher . Sum ( hash [ : 0 ] )
2019-08-23 14:23:11 +00:00
return hash
2019-02-25 22:44:14 +00:00
}
2019-03-17 18:26:35 +00:00
// Hash160 performs sha256 and then ripemd160
2019-10-22 14:56:03 +00:00
// on the given data.
2019-08-23 14:23:11 +00:00
func Hash160 ( data [ ] byte ) util . Uint160 {
h1 := Sha256 ( data )
2019-11-27 09:23:18 +00:00
h2 := RipeMD160 ( h1 . BytesBE ( ) )
2019-02-25 22:44:14 +00:00
2019-12-12 14:58:34 +00:00
return h2
2019-02-25 22:44:14 +00:00
}
2019-03-17 18:26:35 +00:00
// Checksum returns the checksum for a given piece of data
2022-05-12 12:46:27 +00:00
// using DoubleSha256 as the hash algorithm. It returns the
// first 4 bytes of the resulting slice.
2019-08-23 14:08:19 +00:00
func Checksum ( data [ ] byte ) [ ] byte {
hash := DoubleSha256 ( data )
return hash [ : 4 ]
2019-02-25 22:44:14 +00:00
}