IBM / ipfs-social-proof

IPFS Social Proof: A decentralized identity and social proof system
MIT License
142 stars 27 forks source link

[API] ASCII armor for signatures & pub keys #10

Open daviddahl opened 5 years ago

daviddahl commented 5 years ago

edit Looks like a lot of this issue is confusion of key types and not understanding all formats

I have spent a little bit of time figuring out the round trip of RSAPubKey -> Uint8Array -> 'base64' string.

For whatever reason, when TextEncoder - and pretty much all of the base64 -> Uint8Array Array libraries I have found on npm, the returned Uint8Array has the wrong prototype (TypedArray) or the Uint8Array is too short (288 vs 299 length).

I kind of think there is a base64 encoder/ decoder inside IPFS code somewhere, I just have not found it yet.

In the mean time I have declared the public keys as Dehydrated Public Keys and they are merely created like this: plaintext = JSON.stringify([Uint8Array] rsaKeyBytes)

daviddahl commented 5 years ago

I pulled in node-forge directly to use the pki and pem modules. Will need to keep this open to figure out ASCII armor of signatures next

daviddahl commented 5 years ago

My latest discovery is that - even using node-forge when one converts the ascii armored (PEM) public key back to an RsaPublicKey, the verification fails as the key length is shorter - bytes are lost in the procedure I was using: pki.publicKeyFromPem(pemPubKey)

So to document what I am doing is this:

 get pubKeyDehydrated () {
    // get a base64 encoded marshaled pub key
    const pub = this.node._peerInfo.id._privKey.public
    const mk = this._crypto.keys.marshalPublicKey(pub)
    return this.dehydrate(mk)
}

  dehydrate (buff) {
    let s = JSON.stringify(buff)
    let arr = JSON.parse(s).data
    return JSON.stringify(arr)
}

I get the key's byes and JSON stringify then just keep a stringified array of those bytes. To convert back to an RsaPublicKey:

rehydrate (jsonStr) {
    // re-hydrate a json string back into an Uint8Array
    // expecting a string like so: '{"data": [0,2,5,7,12,34,122...]}'
    const obj = JSON.parse(jsonStr)
    // Get the Uint8Array version of the stringified data (key or signature)
    const buff = Buffer.from(obj)
    return buff
  }

Its totally unconventional... Not ideal, but works - for now. A test suite foir the crypto is need to understand what needs to happen here.

daviddahl commented 5 years ago

Ok, we now have merged in #52 which handles converting to PEM encoded public key and back to RSA key that can be used for verification