diff --git a/Cargo.lock b/Cargo.lock
index 8ffe513c7e389617a435ec33f97e3ce0321abbd6..d7a684373e7d3483c38cca2404083b1d8ec4e34b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -268,9 +268,9 @@ dependencies = [
 
 [[package]]
 name = "dup-crypto"
-version = "0.45.0"
+version = "0.46.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58a3b88cbd886b092a7e6c58608d87744706e0fc66a48eaf452c297e5aac3802"
+checksum = "97b1ebfa9edbb53cd4434f01877fcd74fb2416b93a217754d2daecbeecad67eb"
 dependencies = [
  "aes",
  "arrayvec",
diff --git a/native/dubp_rs/Cargo.toml b/native/dubp_rs/Cargo.toml
index b27959de42dbb73aa4e2424b297bb730708bb2fe..05ba6373a8515d25ee82f183d08e814bd3c09051 100644
--- a/native/dubp_rs/Cargo.toml
+++ b/native/dubp_rs/Cargo.toml
@@ -11,7 +11,7 @@ crate-type = ["rlib"]
 
 [dependencies]
 allo-isolate = "0.1.6"
-dup-crypto = { version = "0.45.0", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "scrypt"] }
+dup-crypto = { version = "0.46.0", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "scrypt"] }
 fast-threadpool = { version = "0.3.0", default-features = false }
 once_cell = { version = "1.3.1", default-features = false, features = ["std"] }
 parking_lot = "0.11.1"
diff --git a/native/dubp_rs/src/error.rs b/native/dubp_rs/src/error.rs
index 29a48bceafeed2b3764a050a18868c3d50e5a1e3..0448156b88475f5f5425d62d3dff5e38c71de190 100644
--- a/native/dubp_rs/src/error.rs
+++ b/native/dubp_rs/src/error.rs
@@ -31,6 +31,8 @@ pub(crate) enum DubpError {
     #[error("{0}")]
     InvalidAccountIndex(InvalidAccountIndex),
     #[error("{0}")]
+    InvalidPubkey(PublicKeyFromStrErr),
+    #[error("{0}")]
     InvalidU31(U31Error),
     #[error("Invalid secret code type")]
     InvalidSecretCodeType,
diff --git a/native/dubp_rs/src/lib.rs b/native/dubp_rs/src/lib.rs
index 92b8091205d2b9b696dae193f1cf4ef180948611..37cd38e97acb62090a0b7654b1949a0bed2f4866 100644
--- a/native/dubp_rs/src/lib.rs
+++ b/native/dubp_rs/src/lib.rs
@@ -21,6 +21,7 @@ mod error;
 mod inputs;
 mod legacy;
 mod mnemonic;
+mod pubkey;
 mod secret_code;
 
 use crate::error::{DartRes, DubpError};
@@ -35,8 +36,8 @@ use dup_crypto::{
         ed25519::bip32::{
             ChainCode, InvalidAccountIndex, KeyPair, PrivateDerivationPath, PublicKeyWithChainCode,
         },
-        ed25519::{KeyPairFromSeed32Generator, PublicKey},
-        KeyPair as _, KeyPairEnum, Signator as _, Signature as _,
+        ed25519::{KeyPairFromSeed32Generator, PublicKey, PublicKeyFromStrErr},
+        KeyPair as _, KeyPairEnum, PublicKey as _, Signator as _, Signature as _,
     },
     mnemonic::{Language, Mnemonic, MnemonicType},
     utils::{U31Error, U31},
@@ -83,6 +84,20 @@ pub extern "C" fn change_dewif_secret_code(
     )
 }
 
+#[no_mangle]
+pub extern "C" fn check_pubkey(port: i64, pubkey: *const raw::c_char) {
+    exec_async(port, || Ok(char_ptr_to_str(pubkey)?), pubkey::check_pubkey)
+}
+
+#[no_mangle]
+pub extern "C" fn compute_checksum(port: i64, pubkey: *const raw::c_char) {
+    exec_async(
+        port,
+        || Ok(char_ptr_to_str(pubkey)?),
+        pubkey::compute_checksum,
+    )
+}
+
 #[no_mangle]
 pub extern "C" fn gen_dewif(
     port: i64,
diff --git a/native/dubp_rs/src/pubkey.rs b/native/dubp_rs/src/pubkey.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6c338258f462a8c1ebd75cbf6c211050d4d623d4
--- /dev/null
+++ b/native/dubp_rs/src/pubkey.rs
@@ -0,0 +1,27 @@
+//  Copyright (C) 2020  Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+use crate::*;
+
+pub(crate) fn check_pubkey(pubkey: &str) -> Result<(), DubpError> {
+    PublicKey::from_base58_with_checksum_opt(pubkey).map_err(DubpError::InvalidPubkey)?;
+    Ok(())
+}
+
+pub(crate) fn compute_checksum(pubkey: &str) -> Result<String, DubpError> {
+    Ok(PublicKey::from_base58(pubkey)
+        .map_err(|e| DubpError::InvalidPubkey(PublicKeyFromStrErr::BaseConversionError(e)))?
+        .checksum())
+}
diff --git a/packages/dubp_rs/lib/dubp.dart b/packages/dubp_rs/lib/dubp.dart
index 94382c7fb63a8620aaf72b6c0000675393d59490..a1f903df707087c66ea865cd71a52867a472df08 100644
--- a/packages/dubp_rs/lib/dubp.dart
+++ b/packages/dubp_rs/lib/dubp.dart
@@ -102,6 +102,30 @@ class DubpRust {
     return Future.value(NewWallet._(newWallet[0], newWallet[1]));
   }
 
+  /// Check validity of a base58 public key with its checksum
+  static Future<void> checkPublicKey({String pubkey}) {
+    final completer = Completer<void>();
+    final sendPort =
+        singleCompletePort<void, String>(completer, callback: _handleErrVoid);
+    native.check_pubkey(
+      sendPort.nativePort,
+      Utf8.toUtf8(pubkey),
+    );
+    return completer.future;
+  }
+
+  /// Compute public key checksum
+  static Future<String> computeChecksum({String pubkey}) {
+    final completer = Completer<String>();
+    final sendPort =
+        singleCompletePort<String, String>(completer, callback: _handleErr);
+    native.compute_checksum(
+      sendPort.nativePort,
+      Utf8.toUtf8(pubkey),
+    );
+    return completer.future;
+  }
+
   /// Generate a random mnemonic
   static Future<String> genMnemonic({Language language = Language.english}) {
     final completer = Completer<String>();