Skip to content

Commit 86306d9

Browse files
committed
WIP: sha1, sha224, sha256, sha384, sha512 algos; copy, digest, hexdigest methods; name, block_size, digest_size attributes
1 parent a62cf50 commit 86306d9

2 files changed

Lines changed: 103 additions & 1 deletion

File tree

hashlib/hashlib.go

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ package hashlib
77

88
import (
99
"crypto/md5"
10+
"crypto/sha1"
11+
"crypto/sha256"
12+
"crypto/sha512"
1013
"hash"
1114

1215
"github.com/go-python/gpython/py"
@@ -42,6 +45,16 @@ func hashlib_new(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Object
4245
switch name {
4346
case "md5":
4447
hasher = md5.New()
48+
case "sha1":
49+
hasher = sha1.New()
50+
case "sha224":
51+
hasher = sha256.New224()
52+
case "sha256":
53+
hasher = sha256.New()
54+
case "sha384":
55+
hasher = sha512.New384()
56+
case "sha512":
57+
hasher = sha512.New()
4558
default:
4659
return nil, py.ExceptionNewf(py.ValueError, "unsupported hash type "+name)
4760
}
@@ -57,6 +70,46 @@ func hashlib_md5(self py.Object, arg py.Object) (py.Object, error) {
5770
return py.NewHash("md5", md5.New(), data), nil
5871
}
5972

73+
func hashlib_sha1(self py.Object, arg py.Object) (py.Object, error) {
74+
data, err := py.BytesFromObject(arg)
75+
if err != nil {
76+
return nil, err
77+
}
78+
return py.NewHash("sha1", sha1.New(), data), nil
79+
}
80+
81+
func hashlib_sha224(self py.Object, arg py.Object) (py.Object, error) {
82+
data, err := py.BytesFromObject(arg)
83+
if err != nil {
84+
return nil, err
85+
}
86+
return py.NewHash("sha224", sha256.New224(), data), nil
87+
}
88+
89+
func hashlib_sha256(self py.Object, arg py.Object) (py.Object, error) {
90+
data, err := py.BytesFromObject(arg)
91+
if err != nil {
92+
return nil, err
93+
}
94+
return py.NewHash("sha256", sha256.New(), data), nil
95+
}
96+
97+
func hashlib_sha384(self py.Object, arg py.Object) (py.Object, error) {
98+
data, err := py.BytesFromObject(arg)
99+
if err != nil {
100+
return nil, err
101+
}
102+
return py.NewHash("sha384", sha512.New384(), data), nil
103+
}
104+
105+
func hashlib_sha512(self py.Object, arg py.Object) (py.Object, error) {
106+
data, err := py.BytesFromObject(arg)
107+
if err != nil {
108+
return nil, err
109+
}
110+
return py.NewHash("sha512", sha512.New(), data), nil
111+
}
112+
60113
const hashlib_doc = `hashlib module - A common interface to many hash functions.
61114
new(name, data=b'') - returns a new hash object implementing the
62115
given hash function; initializing the hash
@@ -99,7 +152,12 @@ More condensed:
99152
func init() {
100153
methods := []*py.Method{
101154
py.MustNewMethod("new", hashlib_new, 0, hashlib_new_doc),
102-
py.MustNewMethod("md5", hashlib_md5, 0, ``),
155+
py.MustNewMethod("md5", hashlib_md5, 0, ""),
156+
py.MustNewMethod("sha1", hashlib_sha1, 0, ""),
157+
py.MustNewMethod("sha224", hashlib_sha224, 0, ""),
158+
py.MustNewMethod("sha256", hashlib_sha256, 0, ""),
159+
py.MustNewMethod("sha384", hashlib_sha384, 0, ""),
160+
py.MustNewMethod("sha512", hashlib_sha512, 0, ""),
103161
}
104162
py.NewModule("hashlib", hashlib_doc, methods, nil)
105163
}

py/hash.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,48 @@ func (h Hash) M__le__(other Object) (Object, error) {
8686
return NewBool(bytes.Compare(h.Data, b.Data) <= 0), nil
8787
}
8888

89+
func init() {
90+
HashType.Dict["update"] = MustNewMethod("update", func(self Object, arg Object) (Object, error) {
91+
data, err := BytesFromObject(arg)
92+
if err != nil {
93+
return self, err
94+
}
95+
self.(*Hash).Data = append(self.(*Hash).Data, data...)
96+
return self, nil
97+
}, 0, "update(arg) -> Update the hash object with the object arg, which must be interpretable as a buffer of bytes. Repeated calls are equivalent to a single call with the concatenation of all the arguments: m.update(a); m.update(b) is equivalent to m.update(a+b).")
98+
99+
HashType.Dict["digest"] = MustNewMethod("digest", func(self Object) Bytes {
100+
return Bytes(self.(*Hash).Hasher.Sum(nil))
101+
}, 0, "digest() -> Return the digest of the data passed to the update() method so far. This is a bytes object of size digest_size which may contain bytes in the whole range from 0 to 255.")
102+
103+
HashType.Dict["hexdigest"] = MustNewMethod("hexdigest", func(self Object) String {
104+
return String(fmt.Sprintf("%x", self.(*Hash).Hasher.Sum(nil)))
105+
}, 0, "hexdigest() -> Like digest() except the digest is returned as a string object of double length, containing only hexadecimal digits. This may be used to exchange the value safely in email or other non-binary environments.")
106+
107+
HashType.Dict["copy"] = MustNewMethod("copy", func(self Object) Object {
108+
hash := self.(*Hash)
109+
dst := make([]byte, len(hash.Data))
110+
copy(dst, hash.Data)
111+
return NewHash(hash.Name, hash.Hasher, dst)
112+
}, 0, "copy() -> Return a copy (“clone”) of the hash object. This can be used to efficiently compute the digests of data sharing a common initial substring.")
113+
114+
HashType.Dict["name"] = &Property{
115+
Fget: func(self Object) (Object, error) {
116+
return String(self.(*Hash).Name), nil
117+
},
118+
}
119+
120+
HashType.Dict["block_szie"] = &Property{
121+
Fget: func(self Object) (Object, error) {
122+
return Int(self.(*Hash).Hasher.BlockSize()), nil
123+
},
124+
}
125+
126+
HashType.Dict["digest_size"] = &Property{
127+
Fget: func(self Object) (Object, error) {
128+
return Int(self.(*Hash).Hasher.Size()), nil
129+
},
130+
}
131+
}
132+
89133
var _ richComparison = Hash{}

0 commit comments

Comments
 (0)