# Dongle: a fluent Go crypto package for encoding, hashing and encryption

> Dongle is a Go package that puts encoding, hashing, HMAC, symmetric and asymmetric encryption behind one chained API, with the standard library doing the actual cryptography underneath. It suits Go developers who want consistent call shapes and readable output formats, and the value is in the ergonomics rather than in any algorithm the standard library does not already have.

**dromara/dongle** — A simple, semantic and developer-friendly crypto package for golang

- Repository: https://github.com/dromara/dongle
- Website: https://dongle.go-pkg.com
- Stars: 1,104 · Forks: 83
- Language: Go
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/dromara-dongle

## One chain shape for every operation

Dongle is described as a simple, semantic and developer-friendly golang crypto package, and the design bet is visible in the first example. Every operation follows the same shape: pick a source, pick an algorithm, pick an output format.

Encoding and decoding look like this:

```go
dongle.Encode.FromString("hello world").ByBase64().ToString()      // aGVsbG8gd29ybGQ=
dongle.Decode.FromString("aGVsbG8gd29ybGQ=").ByBase64().ToString() // hello world
```

Hashing adds one method and the same skeleton:

```go
dongle.Hash.FromString("hello world").ByMd5().ToHexString()    // 5eb63bbbe01eeed093cb22bb8f5acdc3
dongle.Hash.FromString("hello world").ByMd5().ToBase64String() // XrY7u+Ae7tCTyyK7j1rNww==
```

HMAC inserts a key step between the source and the algorithm:

```go
dongle.Hash.FromString("hello world").WithKey([]byte("dongle")).ByMd5().ToHexString()
```

That consistency is the package's actual contribution. The algorithms underneath are standard library and `golang.org/x/crypto` work, so what Dongle adds is a single vocabulary for calling them. The consequence is that the output format is chosen at the end of the chain, which removes a whole category of bug where a digest is hex in one call site and base64 in another.

The repository layout matches the split of the API. There is a `coding/` directory for the encodings, a `crypto/` directory for the ciphers, a `hash/` directory for digests and HMAC, an `internal/` directory, a `dongle.go` root file and an `issue_test.go` at the top level.

## The algorithm list covers encodings, digests, ciphers and Chinese suites

The repository topics give an unusually complete picture of the surface, and they read as a feature list.

The encodings are base100, base16, base32, base45, base58, base62, base64, base85 and base91. That is a wide set, and the ones beyond base64 exist for specific reasons, base58 for keys that end up in identifiers, base85 for dense binary in text, base91 for even denser.

The digests and MACs are md5, sha family entries, sm3, and the hmac variants of each. The block ciphers are aes, des and 3des. The asymmetric entries are rsa and sm2, and sm4 is the other Chinese standard in the list.

The SM2, SM3 and SM4 entries are the ones that distinguish this package from a generic wrapper. These are the Chinese national cryptographic standards, and a Go developer working on a system that has to interoperate with a Chinese enterprise deployment needs them, and needs them to produce byte-identical output to the other side.

The dependency list backs the claim that this is a wrapper rather than a provider of new primitives. The module requires `github.com/stretchr/testify` for testing, and `golang.org/x/crypto` at v0.40.0, which is where the additional ciphers and hashes come from. There is no dependency on a native crypto library, no cgo binding and no assembly.

The introduction also claims 100% unit test coverage, and the repository carries a codecov badge alongside a Go Report Card badge and a GitHub Actions test badge, so the coverage claim is at least instrumented.

## Ciphers are configured objects, and the example shows the risk

Symmetric encryption takes a different shape because a cipher needs configuration before it can be used. The example builds one explicitly:

```go
c := cipher.NewAesCipher(cipher.CBC)
c.SetKey([]byte("dongle1234567890"))
c.SetIV([]byte("1234567890123456"))
c.SetPadding(cipher.PKCS7)

dongle.Encrypt.FromString("hello world").ByAes(c).ToHexString()
```

The construction is readable, and every parameter is visible: block mode, key length, initialisation vector, padding scheme. The separate `cipher` package import makes the structure clear, and the setters mean a cipher object carries its own configuration rather than taking a bag of arguments at call time.

The example values are also a teaching hazard, and a reader should read them as such. The key is a literal sixteen byte ASCII string, the IV is a literal sixteen byte ASCII string, and the same IV is reused for every message encrypted with that object. CBC with a fixed IV leaks information about whether two plaintexts share a prefix, and a hardcoded key in a source file is a key in a source file.

The padding note in the comment is the other useful detail. Padding mode only needs setting for the CBC and ECB block modes, because the modes that work on a stream of arbitrary length do not need it.

So the ergonomics are good and the defaults are visible, which is the right combination, but the safety of a real deployment comes from the caller choosing a mode and generating a fresh IV per message. Nothing in the example does that for you.

## RSA goes through a key pair object with explicit padding rules

Asymmetric encryption follows the same configured-object pattern, with a key pair from a `keypair` subpackage:

```go
kp := keypair.NewRsaKeyPair()
kp.SetFormat(keypair.PKCS8)
kp.SetPadding(keypair.OAEP)
kp.SetHash(crypto.SHA256)

kp.SetPublicKey([]byte("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqzZNa9VrcewyU6wDoV7Y9kAHqX1VK0B3Rb6GNmQe4zLEfce7cVTaLrc4VGTKl35tADG1cRHqtaG4S/WttpiGZBhxJy4MpOXb6eIPiVLsn2lL+rJo5XdbSr3gyjxEOQQ97ihtw4lDd5wMo4bIOuw1LtMezHC1outlM6x+/BB0BSQIDAQAB"))

dongle.Encrypt.FromString("hello world").ByRsa(kp).ToHexString()
```

The comments carry the defaults, and they are the most useful part of this example. The key format defaults to PKCS8. The padding mode defaults to empty, with the rule that the PKCS1 format defaults to PKCS1v15 and the PKCS8 format defaults to OAEP. The hash algorithm defaults to SHA256 and is used for the OAEP padding mode.

That is a slightly awkward default scheme, since the effective padding depends on the format you set, and a reader who sets a format without reading the comment changes which padding they get. Being explicit is the safe path, and the API allows it in one line.

Decryption mirrors encryption with the private key set on the same object, and the source of the ciphertext is selected by its encoding, with `FromHexString` and `FromBase64String` giving the plaintext back.

The keys are passed in as raw byte strings, which means the caller handles PEM parsing, key storage and rotation. That is a sensible division of labour for a crypto utility package, and also a reminder that the hard part of RSA is not the encryption call.

## Installation, the dromara move, and the Go version floor

Installation is a `go get`, and the README gives three mirrors because the project is hosted on more than one service:

```go
go get -u github.com/dromara/dongle
```

The requirement is Go 1.23 or later, stated as `go version >= 1.23`, and the module file confirms it with `go 1.23.0` in the go directive.

The gitee and gitcode mirrors are listed alongside GitHub, and that pattern is not a stylistic choice. The project was donated to the dromara organisation, and the repository URL changed as a result, which broke imports for existing users. The documentation handles the migration explicitly: if the previous repository used was `golang-module/dongle`, you replace it in `go.mod`, or run the module edit command:

```go
go mod edit -replace github.com/golang-module/dongle = github.com/dromara/dongle
```

A `replace` directive is a reasonable way to make an existing build work while you change the import paths, though it is a transition mechanism rather than a permanent arrangement, since the module path in the source still has to change eventually.

The README is also published in Simplified Chinese and Japanese alongside English, and the project site at dongle.go-pkg.com carries the API reference.

On versions, the release history shows v1.2.1 on 2025-11-24, v1.2.2 on 2025-12-08 and v1.2.3 on 2025-12-16, and the last push was on 2026-10-19. The repository is not archived, and the licence is MIT.

## Where Dongle stops and the standard library starts

It is worth being blunt about what this package is not. It is not a cryptography provider. Every algorithm it exposes comes from `crypto/aes`, `crypto/des`, `crypto/md5`, `crypto/rsa`, `crypto/sha256`, `crypto/hmac` and `golang.org/x/crypto`, and the wrappers add call shape, not security.

That has two implications. The first is that the standard library remains the right choice for anything where you care about the exact behaviour of the primitive, because there is no added indirection to reason about. The second is that a wrapper is a place where defaults hide. The RSA case shows it, where the effective padding depends on the key format you set, and the AES example shows it, where CBC and a fixed IV are the demonstrable path of least resistance.

The second limitation is that the convenience stops at the encoding step. Anything that needs key derivation, key storage, rotation or a password based scheme is not in the package. The HMAC example takes a key as a byte slice, which means the caller has already decided where the key comes from and how it is protected, and the package has no opinion about that. For a system where the key comes from a secret manager and rotates, that is exactly the split you want. For a system where the key is a user's password, Dongle does not solve the problem, because a password needs a key derivation function and a salt, and the package does not provide one.

The alternative approach is to call the standard library directly. The difference in approach is a matter of verbosity and consistency rather than capability. Direct calls are shorter in total lines for a one-off hash, and they are explicit about every parameter, which matters for a security library. Dongle earns its place in a codebase with many call sites, where the same three line shape appears in twenty places and the format of the output is the thing most likely to be wrong.

One last practical note. The project won the gitee 2024 Most Valuable Project and gitcode 2024 Open Source Star Project awards, and it is listed in awesome-go, and the introduction describes it as having 100% unit test coverage. None of that is a reason to adopt a crypto package. The reason to adopt it is that the API is consistent and the test coverage means the encoding and formatting behaviour you depend on is pinned.

## Conclusion

Dongle fits a Go codebase that has accumulated ad hoc conversion code, where a hash result is sometimes hex and sometimes base64 and nobody can remember which, because the chained API makes the output format part of the call rather than a separate conversion step. Skip it if you want algorithms it does not wrap, since it is a convenience layer over the standard library and `golang.org/x/crypto` rather than a provider of new primitives, and be careful with the symmetric cipher defaults, because the example uses AES in CBC mode with PKCS7 padding and a fixed key and IV, which is fine for a test and wrong for production. Before adopting, read the cipher construction code and decide your mode and your key handling yourself, and note the project moved to the dromara organisation, so the module path in your `go.mod` needs updating if you used the old `golang-module/dongle` path.

## FAQ

### How do I install Dongle in a Go project?

Run `go get -u github.com/dromara/dongle`, with Go 1.23 or later required. The README also lists gitee and gitcode mirrors, and notes that the project moved from the `golang-module/dongle` path, which can be redirected with `go mod edit -replace`.

### What is the Dongle API shape?

Each call chains a source, an operation and an output format, for example `dongle.Hash.FromString("hello world").ByMd5().ToHexString()`, and HMAC inserts a `WithKey` step before the algorithm.

### Which algorithms does Dongle support?

The repository topics list encodings from base16 to base100 including base32, base45, base58, base62, base85 and base91, the digests md5, sha family and sm3, the ciphers aes, des and 3des, and the asymmetric algorithms rsa and sm2, plus sm4.

### How do I set up AES encryption with Dongle?

Create a cipher with `cipher.NewAesCipher(cipher.CBC)`, then call `SetKey`, `SetIV` and, for the CBC and ECB block modes, `SetPadding`, and pass the object to `ByAes` on the encrypt or decrypt chain.

### What licence is Dongle released under?

MIT. The repository carries a LICENSE file, and the README links the licence badge to it.

## Sources

- [dromara/dongle on GitHub](https://github.com/dromara/dongle)
- [License: MIT](https://github.com/dromara/dongle/blob/master/LICENSE)
- [Project website](https://dongle.go-pkg.com)
- [README](https://github.com/dromara/dongle/blob/master/README.md)
- [Releases](https://github.com/dromara/dongle/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dromara-dongle
