Stampery Blockchain Add-in for Microsoft Office

Ville Rantala

This is just one of many blockchain related projects at Microsoft.  For others, see

Partner Scenario

Stampery provides the ability to certify and verify documents against both Ethereum Classic and Bitcoin blockchains via a web page and also through a programmatic API. They wanted to improve their enterprise customer reach by adding Microsoft Office as a client in their present solution.

This code story covers how we created an add-in for Microsoft Office that communicates over REST with an Azure Node.js server, which then calls the Stampery API.


Enterprise organizations keep many important records in Office, such as contracts and other legal documents. It is valuable for users to be able to certify or sign these documents, to verify they have not been altered. That is, users should be able to see that documents sent to them are signed or stamped, then verified or notarized.

Various companies sell such a certification function and store the document’s signature so that it can be verified at a later date. This approach, of course, relies on the company ensuring the privacy of the document, as well as their continued ability to validate it in the future.

An alternative to relying on a single entity (commercial, public, government, etc.) to keep such proof of identity safe is to create a hash of the document and send that hash to the publicly accessible blockchain, such as Bitcoin. Once the hash data is present on the public blockchain, the document can’t be changed without invalidating the hash. This approach guarantees both the document’s privacy and the data’s availability for future validation purposes.

Stampery provides this functionality today by creating hashes of documents submitted through the web and storing them on the Ethereum Classic and Bitcoin public blockchains. To enable this capability, Stampery provides a RESTful API that is accessible from applications.

In this project, we leveraged this secure API to create a convenient add-in to Microsoft Outlook that performs like a near-native feature to stamp/certify an email without leaving Outlook or even the specific email that you are viewing. The solution provides document certification (creation of a stamp) and verification (checking a document against a stamp) in Office using the Stampery API and the public blockchain.

Solution Overview

The manifest file in the Office add-in creates certification and verification buttons in the toolbar of Outlook documents.

Image doc 1024 215 366


Pressing the certification button calls a JavaScript function in Office. This function hashes the document and sends the sha256 hash to a Node.js server as a REST call, so the document never leaves Office. The Node.js server runs as an Azure App Service and keeps a copy of the hash for later verification before calling the Stampery API with the hash. The Stampery service then takes the hash and puts it onto the public Ethereum Classic and Bitcoin blockchains.


Pressing the verification button calls the Javascript function from the certification process again, which hashes the document and sends the hash to the Node.js server as a REST call. The Node.js server then calls the Stampery API to access the original hash for the document from both blockchains. It compares the two hashes and returns a verified result if they are the same. The Microsoft Office client (either the Outlook client or the browser client) then displays a verification message to show that the document is unchanged (or not).


Image architecture

For additional details, please refer to the GitHub repo.


The add-in is implemented in JavaScript running in Microsoft Office and with a Node.js server. In Office, there is a manifest which allows add-ins for the document and a set of functions which provide the service. The Node.js server provides the REST service to connect to the Office functions and to communicate with the Stampery API.

Office Manifest

The Office manifest provides two add-in buttons, “Certify” and “Verify,” along with their associated comments and status information.

The certification button (stamp function) looks like:

                <Control xsi:type="Button" id="stampFunctionButton">
                  <Label resid="funcStampButtonLabel" />
                    <Title resid="funcStampSuperTipTitle" />
                    <Description resid="funcStampSuperTipDescription" />
                    <bt:Image size="16" resid="icon-16" />
                    <bt:Image size="32" resid="icon-32" />
                    <bt:Image size="80" resid="icon-80" />
                  <Action xsi:type="ExecuteFunction">

The verification button (prove function) looks like:

                <Control xsi:type="Button" id="proveFunctionButton">
                  <Label resid="funcProveButtonLabel" />
                    <Title resid="funcProveSuperTipTitle" />
                    <Description resid="funcProveSuperTipDescription" />
                    <bt:Image size="16" resid="icon-16" />
                    <bt:Image size="32" resid="icon-32" />
                    <bt:Image size="80" resid="icon-80" />
                  <Action xsi:type="ExecuteFunction">

Below are the associated comments:

        <bt:String id="groupLabel" DefaultValue="Stampery"/>

        <bt:String id="funcStampButtonLabel" DefaultValue="Certify" />
        <bt:String id="funcStampSuperTipTitle" DefaultValue="Certify" />

        <bt:String id="funcProveButtonLabel" DefaultValue="Verify" />
        <bt:String id="funcProveSuperTipTitle" DefaultValue="Verify" />
        <bt:String id="funcStampSuperTipDescription" DefaultValue="Certify this email using Stampery" />
        <bt:String id="funcProveSuperTipDescription" DefaultValue="Verify the validaty of the Stampery proof for this document" />

Office Functions

The JavaScript running in Office has two functions: stamp and prove. These functions retrieve the document body (not the metadata) from Office and then hash it. This hash is then posted to the Node.js server (in the case of stamp), or the proof of the hash is requested from the server (in the case of prove). We then compare the returned hash to the computed one; if they are the same, then a success message is displayed in Office.

function stamp(event) {
  hashMail(Office.context.mailbox.item, function (hash) {
    postHash({ hash: hash }, function (response) {
      if (response.error) {
        showMessage(response.error, event);
      } else {
        showMessage('Successfully stamped', event);

function prove(event) {
  hashMail(Office.context.mailbox.item, function (hash) {
    getProof(hash, function (response) {
      if (response.error) {
      var result = response.result;
      proof = result.btc || result.eth;
      if (proof) {
        checkSiblings(hash, proof.siblings, proof.root, function (validity) {
          var chain = [null, 'Bitcoin', 'Ethereum'][Math.abs(proof.anchor.chain)];
          showMessage('Valid ' + chain + ' proof: ' + validity, event);
      } else {
        showMessage('Still working on it..', event);

The hash is:

function hashMail(item, callback) {
  Office.context.mailbox.item.body.getAsync('text', {}, function (result) {
    if (result.status === Office.AsyncResultStatus.Failed) {
    var body = result.value;
    var hash = keccak_512(body);

The REST calls to the Node.js server api.js are:

function postHash(hash, callback) {
  var xhr = new XMLHttpRequest();'POST', '/api/stamp');
  xhr.setRequestHeader('Content-Type', 'application/json');
  handleRequest(xhr, hash, callback);

function getProof(hash, callback) {
  var xhr = new XMLHttpRequest();'GET', '/api/proofs/' + hash);
  handleRequest(xhr, null, callback);

Node.js Server

On a stamp, the Node.js server calls the Stampery API with the hash and adds it to the proofsDict array for verification.'/stamp', function (req, res) {
  var hash = req.body.hash;

  // Perform actual stamping and return success or error
  if (stampery.stamp(hash)) {
    // Create an entry for hash in proofsDict
    proofsDict[hash] = {eth: null, btc: null};
    res.send({result: hash, error: null});
  }  else {
    res.status(503).send({error: 'Stamping Failed'});

On a proof, the Node.js server checks in the proofsDict array to see if the stamp is valid. In the initial implementation, an in-memory JavaScript object was used to store the hashes generated. In the future, the Stampery API is being enhanced to include secure storage of the hashes so that the in-memory object is no longer required. If the stamp is valid, it returns the following result.

router.get('/proofs/:hash', function (req, res) {
  var hash = req.params.hash;

  // Check if stamp exists
  if (!(hash in proofsDict))
    return res.status(404).send({error: 'Stamp Not Found'});

  var proofs = proofsDict[hash];

  res.send({result: proofs, error: null});


The Microsoft Office add-in for the Stampery API and service allows users to certify and verify documents on the Ethereum Classic and Bitcoin blockchains. This method helps users employ the most appropriate, secure method to store both the document and the hash. As a result, enterprise customers who depend on Microsoft Office can now utilize blockchain technology and the Stampery service to confirm the validity of their important Office documents.

Opportunities for Reuse

This solution is reusable for all Microsoft Office products and ERP applications such as Dynamics. In a more general sense, anyone wanting to certify and verify any digital asset could reuse and build upon this knowledge, too. The code example for Office is open source and available on GitHub.


Discussion is closed. Login to edit/delete existing comments.

  • Mikel A. 0

    Please could you explain me how to install de Stampery add-on?
    I can’t find it in the Office Store.
    Thanks in advance!

Feedback usabilla icon