diff --git a/src/crypto.mjs b/src/crypto.mjs
index eea4cb85e87fd1f7905b4f9653dabae8848b6505..b0614ca99f0fe5eeb30372893ef0dea272e3e7f5 100644
--- a/src/crypto.mjs
+++ b/src/crypto.mjs
@@ -2,9 +2,9 @@
 // Alt deps :  import scrypt from "ecma-nacl/build/lib/scrypt/scrypt.js";
 import nacl from '../generated/vendors/nacl.mjs';
 // Alt import * as ed25519 from '../node_modules/noble-ed25519/index.mjs';
-import {b58,b64} from './basex.mjs';
+import {b58, b64} from './basex.mjs';
 
-export {b58,b64};
+export {b58, b64};
 import sha from '../node_modules/js-sha256/src/sha256.mjs';
 
 const sha256 = sha();
@@ -34,6 +34,7 @@ export async function idSecPass2cleanKeys(idSec, pass) {
 export function seed2keyPair(seed) {
 	return generateKeypair(seed);
 }
+
 /* Noble edition
 export async function seed2keyPair(rawSeed) {
 	const pubKey = await ed25519.getPublicKey(rawSeed);
@@ -90,6 +91,7 @@ export function b58pubKey2bin(b58pubKey) {
 	binPubKey.set(decoded, 32 - decoded.length);
 	return binPubKey;
 }
+
 export function b58secretKey2bin(b58secretKey) {
 	const binSecretKey = new Uint8Array(64);
 	const decoded = b58.decode(b58secretKey);
@@ -112,9 +114,29 @@ export function checkKey(pubKeyWithChecksum) {
 	throw new Error('Bad checksum');
 }
 
-export function sign(unsignedDocument,secretKey){
+export async function signDocument(unsignedDocument, secretKey) {
+	const signHash = await sign(unsignedDocument.trim() + '\n', secretKey)
+	return `${unsignedDocument.trim()}\n${signHash}`;
+}
+
+export async function sign(str, secretKey, outputFormat = 'b64') {
 	const encoder = new TextEncoder();
-	const rawSign = nacl.sign.detached(encoder.encode(unsignedDocument.trim()+'\n'), b58secretKey2bin(secretKey));
-	const b64Sign = b64.encode(rawSign);
-	return `${unsignedDocument.trim()}\n${b64Sign}`;
+	const raw = await rawSign(encoder.encode(str), b58secretKey2bin(secretKey).slice(0, 32));
+	switch (outputFormat.toLocaleLowerCase()) {
+		case 'raw':
+		case 'array':
+		case 'uint8array':
+			return raw;
+		case 'b64':
+			return b64.encode(raw);
+		case 'b58':
+			return b58.encode(raw);
+		default:
+			throw new Error(`OutputFormat ${outputFormat} not handled.`);
+	}
+}
+
+export async function rawSign(uint8Array, rawSeed) {
+	const keys = await seed2keyPair(rawSeed);
+	return nacl.sign.detached(uint8Array, keys.secretKey);
 }
diff --git a/src/crypto.test.mjs b/src/crypto.test.mjs
index f60c4d7d6544880ff19b0766c83356685c451d1c..20c65b72ba9d8936f7a989a55be123b43cb82bd1 100644
--- a/src/crypto.test.mjs
+++ b/src/crypto.test.mjs
@@ -7,13 +7,13 @@ const mdp = 'b';
 const pubKey = 'AoxVA41dGL2s4ogMNdbCw3FFYjFo5FPK36LuiW1tjGbG';
 const secretKey = '3ZsmZhnRv137dS1s7Q3jFGKLTDyhkwguPHfnWBxzDCTTHKWGnYw9zBk3gcCUJCc72TEUuyzM7cqpo7c5LYhs1Qtv';
 const seed = '9eADqX8V6VcPdJCHCVYiE1Vnift9nFNrvr9aTaXA5RJc';
-const unsignedDocument = `Version: 10
+const unsignedDocument = `
+Version: 10
 Type: Identity
 Currency: duniter_unit_test_currency
 Issuer: AoxVA41dGL2s4ogMNdbCw3FFYjFo5FPK36LuiW1tjGbG
 UniqueID: tic
-Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
-`;
+Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855`;
 const signedDocument = `Version: 10
 Type: Identity
 Currency: duniter_unit_test_currency
@@ -21,7 +21,14 @@ Issuer: AoxVA41dGL2s4ogMNdbCw3FFYjFo5FPK36LuiW1tjGbG
 UniqueID: tic
 Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
 8BZ2NE/d4YO2rOFpJFZdEYTIoSL4uSX9zo6tacpHBcCIlSlhkHTIHbSJNuzLl9uVBIO0skI7NZPxEYXIJGQYBg==`;
-test('sign document', async t => t.is(await app.sign(unsignedDocument,secretKey), signedDocument));
+
+test('signDocument', async t => t.is(await app.signDocument(unsignedDocument,secretKey), signedDocument));
+test('b64 sign string', async t => t.is(await app.sign(unsignedDocument,secretKey), 'G6ma6n+rpJ+7PPsUuJjNtzfGQqLWNqRToSlurt8vjrHa7G0tm7oVObJjQBWGMK0zs4/25xXidT19RrfZqWV/DQ=='));
+test('b58 sign string', async t => t.is(await app.sign(unsignedDocument,secretKey,'b58'), 'Z5W7C7ZUwTRPRTCrXtRqmY4WakgEXAkPBDiVEVxoTwrCSvDrup19sENe9tfFNMFKL9ZFdiFWJCSJ2ftgeeDzFsz'));
+test('raw sign string', async t => t.is((await app.sign(unsignedDocument,secretKey,'raw'))[0], 27));
+test('array sign string', async t => t.is((await app.sign(unsignedDocument,secretKey,'Array'))[0], 27));
+test('uint8array sign string', async t => t.is((await app.sign(unsignedDocument,secretKey,'uint8array'))[0], 27));
+test('sign throw for bad output format', async t => t.throwsAsync(()=>app.sign(unsignedDocument,secretKey,'whattt ?')));
 
 test('b58 should decode/encode well', t => t.is(app.b58.encode(app.b58.decode(pubKey)), pubKey));
 test('b58 on pubKey with leading 1', t => t.is(app.b58.encode(app.b58.decode('12BjyvjoAf5qik7R8TKDJAHJugsX23YgJGi2LmBUv2nx')), '12BjyvjoAf5qik7R8TKDJAHJugsX23YgJGi2LmBUv2nx'));