oydid 0.4.0 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/oydid/basic.rb +65 -3
- data/lib/oydid/didcomm.rb +120 -0
- data/lib/oydid/log.rb +17 -14
- data/lib/oydid.rb +12 -6
- metadata +17 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 56c65853f4983bcb8214a4027986839c0503adcc1133933f817d8401d8881be7
         | 
| 4 | 
            +
              data.tar.gz: 2a6048ab2023f8641e83e7b0162a8c15ef6bdb2c0855d70cef8d6c015ca34720
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 799e94f77486d60beb09c8b8f5101ac5789eb1d000052a1aa396121acbd13e0a935cb06fe0c1849ef4deb75b407da049d1111bd15f0d49bd2863671419da4480
         | 
| 7 | 
            +
              data.tar.gz: d513c74e0b307a74a9c7fced1bd3ce5bdaef1941290a70aef447a183e3e31da5c44582d25969cd401ec25379412fb7850d55e5e547972e87ee39e4297e79866c
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.4. | 
| 1 | 
            +
            0.4.4
         | 
    
        data/lib/oydid/basic.rb
    CHANGED
    
    | @@ -25,6 +25,11 @@ class Oydid | |
| 25 25 | 
             
                    message.to_json_c14n
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| 28 | 
            +
                def self.percent_encode(did)
         | 
| 29 | 
            +
                    # remove "https://" from string as it is default
         | 
| 30 | 
            +
                    did = did.sub("https://","").sub("@", "%40").sub("http://","http%3A%2F%2F")
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 28 33 | 
             
                # key management ----------------------------
         | 
| 29 34 | 
             
                def self.generate_private_key(input, method = "ed25519-priv")
         | 
| 30 35 | 
             
                    begin
         | 
| @@ -47,13 +52,21 @@ class Oydid | |
| 47 52 | 
             
                    return [encode([omc, length, raw_key].pack("SCa#{length}")), ""]
         | 
| 48 53 | 
             
                end
         | 
| 49 54 |  | 
| 50 | 
            -
                def self.public_key(private_key)
         | 
| 55 | 
            +
                def self.public_key(private_key, method = "ed25519-pub")
         | 
| 51 56 | 
             
                    code, length, digest = decode(private_key).unpack('SCa*')
         | 
| 52 57 | 
             
                    case Multicodecs[code].name
         | 
| 53 58 | 
             
                    when 'ed25519-priv'
         | 
| 54 | 
            -
                         | 
| 59 | 
            +
                        case method
         | 
| 60 | 
            +
                        when 'ed25519-pub'
         | 
| 61 | 
            +
                            public_key = Ed25519::SigningKey.new(digest).verify_key
         | 
| 62 | 
            +
                        when 'x25519-pub'
         | 
| 63 | 
            +
                            public_key = RbNaCl::PrivateKey.new(digest).public_key
         | 
| 64 | 
            +
                        else
         | 
| 65 | 
            +
                            return [nil, "unsupported key codec"]
         | 
| 66 | 
            +
                        end
         | 
| 55 67 | 
             
                        length = public_key.to_bytes.bytesize
         | 
| 56 | 
            -
                        return [encode([Multicodecs[ | 
| 68 | 
            +
                        return [encode([Multicodecs[method].code, length, public_key].pack("CCa#{length}")), ""]
         | 
| 69 | 
            +
             | 
| 57 70 | 
             
                    else
         | 
| 58 71 | 
             
                        return [nil, "unsupported key codec"]
         | 
| 59 72 | 
             
                    end
         | 
| @@ -91,6 +104,53 @@ class Oydid | |
| 91 104 | 
             
                    end
         | 
| 92 105 | 
             
                end
         | 
| 93 106 |  | 
| 107 | 
            +
                def self.encrypt(message, public_key)
         | 
| 108 | 
            +
                    begin
         | 
| 109 | 
            +
                        code, length, digest = decode(public_key).unpack('CCa*')
         | 
| 110 | 
            +
                        case Multicodecs[code].name
         | 
| 111 | 
            +
                        when 'x25519-pub'
         | 
| 112 | 
            +
                            pubKey = RbNaCl::PublicKey.new(digest)
         | 
| 113 | 
            +
                            authHash = RbNaCl::Hash.sha256('auth'.dup.force_encoding('ASCII-8BIT'))
         | 
| 114 | 
            +
                            authKey = RbNaCl::PrivateKey.new(authHash)
         | 
| 115 | 
            +
                            box = RbNaCl::Box.new(pubKey, authKey)
         | 
| 116 | 
            +
                            nonce = RbNaCl::Random.random_bytes(box.nonce_bytes)
         | 
| 117 | 
            +
                            msg = message.force_encoding('ASCII-8BIT')
         | 
| 118 | 
            +
                            cipher = box.encrypt(nonce, msg)
         | 
| 119 | 
            +
                            return [
         | 
| 120 | 
            +
                                { 
         | 
| 121 | 
            +
                                    value: cipher.unpack('H*')[0], 
         | 
| 122 | 
            +
                                    nonce: nonce.unpack('H*')[0]
         | 
| 123 | 
            +
                                }, ""
         | 
| 124 | 
            +
                            ]
         | 
| 125 | 
            +
                        else
         | 
| 126 | 
            +
                            return [nil, "unsupported key codec"]
         | 
| 127 | 
            +
                        end
         | 
| 128 | 
            +
                    rescue
         | 
| 129 | 
            +
                        return [nil, "encryption failed"]
         | 
| 130 | 
            +
                    end
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                def self.decrypt(message, private_key)
         | 
| 134 | 
            +
                    begin
         | 
| 135 | 
            +
                        cipher = [JSON.parse(message)["value"]].pack('H*')
         | 
| 136 | 
            +
                        nonce = [JSON.parse(message)["nonce"]].pack('H*')
         | 
| 137 | 
            +
                        code, length, digest = decode(private_key).unpack('SCa*')
         | 
| 138 | 
            +
                        case Multicodecs[code].name
         | 
| 139 | 
            +
                        when 'ed25519-priv'
         | 
| 140 | 
            +
                            privKey = RbNaCl::PrivateKey.new(digest)
         | 
| 141 | 
            +
                            authHash = RbNaCl::Hash.sha256('auth'.dup.force_encoding('ASCII-8BIT'))
         | 
| 142 | 
            +
                            authKey = RbNaCl::PrivateKey.new(authHash).public_key
         | 
| 143 | 
            +
                            box = RbNaCl::Box.new(authKey, privKey)
         | 
| 144 | 
            +
                            retVal = box.decrypt(nonce, cipher)
         | 
| 145 | 
            +
                            return [retVal, ""]
         | 
| 146 | 
            +
                        else
         | 
| 147 | 
            +
                            return [nil, "unsupported key codec"]
         | 
| 148 | 
            +
                        end
         | 
| 149 | 
            +
                    rescue
         | 
| 150 | 
            +
                        return [nil, "decryption failed"]
         | 
| 151 | 
            +
                    end
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 94 154 | 
             
                def self.read_private_key(filename)
         | 
| 95 155 | 
             
                    begin
         | 
| 96 156 | 
             
                        f = File.open(filename)
         | 
| @@ -157,6 +217,7 @@ class Oydid | |
| 157 217 |  | 
| 158 218 | 
             
                    case doc_location
         | 
| 159 219 | 
             
                    when /^http/
         | 
| 220 | 
            +
                        doc_location = doc_location.sub("%3A%2F%2F","://")
         | 
| 160 221 | 
             
                        retVal = HTTParty.get(doc_location + "/doc/" + doc_hash)
         | 
| 161 222 | 
             
                        if retVal.code != 200
         | 
| 162 223 | 
             
                            msg = retVal.parsed_response("error").to_s rescue "invalid response from " + doc_location.to_s + "/doc/" + doc_hash.to_s
         | 
| @@ -190,6 +251,7 @@ class Oydid | |
| 190 251 |  | 
| 191 252 | 
             
                    case doc_location
         | 
| 192 253 | 
             
                    when /^http/
         | 
| 254 | 
            +
                        doc_location = doc_location.sub("%3A%2F%2F","://")
         | 
| 193 255 | 
             
                        retVal = HTTParty.get(doc_location + "/doc_raw/" + doc_hash)
         | 
| 194 256 | 
             
                        if retVal.code != 200
         | 
| 195 257 | 
             
                            msg = retVal.parsed_response("error").to_s rescue "invalid response from " + doc_location.to_s + "/doc/" + doc_hash.to_s
         | 
| @@ -0,0 +1,120 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class Oydid
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                # DIDComm Plain Message ---------------------
         | 
| 7 | 
            +
                def self.dcpm(payload, options)
         | 
| 8 | 
            +
                    dcDoc = {}
         | 
| 9 | 
            +
                    dcDoc["id"] = SecureRandom.random_number(10e14).to_i
         | 
| 10 | 
            +
                    dcDoc["type"] = options[:didcomm_type]
         | 
| 11 | 
            +
                    if !options[:didcomm_from_did].nil?
         | 
| 12 | 
            +
                        dcDoc["from"] = options[:didcomm_from_did]
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                    dcDoc["to"] = [options[:didcomm_to_did]]
         | 
| 15 | 
            +
                    dcDoc["created_time"] = Time.now.utc.to_i
         | 
| 16 | 
            +
                    dcDoc["body"] = payload
         | 
| 17 | 
            +
                    return [dcDoc, ""]
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                # DIDComm Signed Message --------------------
         | 
| 22 | 
            +
                def self.dcsm(payload, private_key_encoded, options)
         | 
| 23 | 
            +
                    error = ""
         | 
| 24 | 
            +
                    code, length, digest = decode(private_key_encoded).unpack('SCa*')
         | 
| 25 | 
            +
                    case Multicodecs[code].name
         | 
| 26 | 
            +
                    when 'ed25519-priv'
         | 
| 27 | 
            +
                        private_key = RbNaCl::Signatures::Ed25519::SigningKey.new(digest)
         | 
| 28 | 
            +
                        token = JWT.encode payload, private_key, 'ED25519', { typ: 'JWM', kid: options[:sign_did].to_s, alg: 'ED25519' }
         | 
| 29 | 
            +
                    else
         | 
| 30 | 
            +
                        token = nil
         | 
| 31 | 
            +
                        error = "unsupported key codec"
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
                    return [token, error]
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def self.dcsm_verify(token, options)
         | 
| 37 | 
            +
                    error = ""
         | 
| 38 | 
            +
                    decoded_payload = JWT.decode token, nil, false
         | 
| 39 | 
            +
                    pubkey_did = decoded_payload.last["kid"]
         | 
| 40 | 
            +
                    result, msg = Oydid.read(pubkey_did, options)
         | 
| 41 | 
            +
                    public_key_encoded = Oydid.w3c(result, options)["authentication"].first["publicKeyMultibase"]
         | 
| 42 | 
            +
                    begin
         | 
| 43 | 
            +
                        code, length, digest = Oydid.decode(public_key_encoded).unpack('CCa*')
         | 
| 44 | 
            +
                        case Multicodecs[code].name
         | 
| 45 | 
            +
                        when 'ed25519-pub'
         | 
| 46 | 
            +
                            public_key = RbNaCl::Signatures::Ed25519::VerifyKey.new(digest)
         | 
| 47 | 
            +
                            payload = JWT.decode token.to_s, public_key, true, { algorithm: 'ED25519' }
         | 
| 48 | 
            +
                        else
         | 
| 49 | 
            +
                            payload = nil
         | 
| 50 | 
            +
                            error = "unsupported key codec"
         | 
| 51 | 
            +
                        end
         | 
| 52 | 
            +
                        return [payload, error]
         | 
| 53 | 
            +
                    rescue
         | 
| 54 | 
            +
                        return [nil, "verification failed"]
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                # encryption -----------------------------------
         | 
| 59 | 
            +
                def self.msg_encrypt(payload, private_key_encoded, did)
         | 
| 60 | 
            +
                    error = ""
         | 
| 61 | 
            +
                    code, length, digest = decode(private_key_encoded).unpack('SCa*')
         | 
| 62 | 
            +
                    case Multicodecs[code].name
         | 
| 63 | 
            +
                    when 'ed25519-priv'
         | 
| 64 | 
            +
                        private_key = RbNaCl::Signatures::Ed25519::SigningKey.new(digest)
         | 
| 65 | 
            +
                        token = JWT.encode payload, private_key, 'ED25519'
         | 
| 66 | 
            +
                    else
         | 
| 67 | 
            +
                        token = nil
         | 
| 68 | 
            +
                        error = "unsupported key codec"
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                    return [token, error]
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def self.msg_decrypt(token, public_key_encoded)
         | 
| 74 | 
            +
                    error = ""
         | 
| 75 | 
            +
                    code, length, digest = Oydid.decode(public_key_encoded).unpack('CCa*')
         | 
| 76 | 
            +
                    case Multicodecs[code].name
         | 
| 77 | 
            +
                    when 'ed25519-pub'
         | 
| 78 | 
            +
                        public_key = RbNaCl::Signatures::Ed25519::VerifyKey.new(digest)
         | 
| 79 | 
            +
                        payload = JWT.decode token.to_s, public_key, true, { algorithm: 'ED25519' }
         | 
| 80 | 
            +
                    else
         | 
| 81 | 
            +
                        payload = nil
         | 
| 82 | 
            +
                        error = "unsupported key codec"
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
                    return [payload, error]
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                # signing for JWS ---------------------------
         | 
| 88 | 
            +
                def self.msg_sign(payload, hmac_secret)
         | 
| 89 | 
            +
                    token = JWT.encode payload, hmac_secret, 'HS256'
         | 
| 90 | 
            +
                    return [token, ""]
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def self.msg_verify_jws(token, hmac_secret)
         | 
| 94 | 
            +
                    begin
         | 
| 95 | 
            +
                        decoded_token = JWT.decode token, hmac_secret, true, { algorithm: 'HS256' }
         | 
| 96 | 
            +
                        return [decoded_token, ""]
         | 
| 97 | 
            +
                    rescue
         | 
| 98 | 
            +
                        return [nil, "verification failed"]
         | 
| 99 | 
            +
                    end
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                # DID Auth for data container with challenge ---
         | 
| 103 | 
            +
                def self.token_from_challenge(host, pwd)
         | 
| 104 | 
            +
                    sid = SecureRandom.hex(20).to_s
         | 
| 105 | 
            +
                    retVal = HTTParty.post(host + "/oydid/init",
         | 
| 106 | 
            +
                                headers: { 'Content-Type' => 'application/json' },
         | 
| 107 | 
            +
                                body: { "session_id": sid }.to_json )
         | 
| 108 | 
            +
                    challenge = retVal.parsed_response["challenge"]
         | 
| 109 | 
            +
                    signed_challenge = Oydid.sign(challenge, Oydid.generate_private_key(pwd).first).first
         | 
| 110 | 
            +
                    public_key = Oydid.public_key(Oydid.generate_private_key(pwd).first).first
         | 
| 111 | 
            +
                    retVal = HTTParty.post(host + "/oydid/token",
         | 
| 112 | 
            +
                                headers: { 'Content-Type' => 'application/json' },
         | 
| 113 | 
            +
                                body: {
         | 
| 114 | 
            +
                                    "session_id": sid,
         | 
| 115 | 
            +
                                    "signed_challenge": signed_challenge,
         | 
| 116 | 
            +
                                    "public_key": public_key
         | 
| 117 | 
            +
                                }.to_json)
         | 
| 118 | 
            +
                    return retVal.parsed_response["access_token"]
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
            end
         | 
    
        data/lib/oydid/log.rb
    CHANGED
    
    | @@ -37,6 +37,7 @@ class Oydid | |
| 37 37 |  | 
| 38 38 | 
             
                    case log_location
         | 
| 39 39 | 
             
                    when /^http/
         | 
| 40 | 
            +
                        log_location = log_location.sub("%3A%2F%2F","://")
         | 
| 40 41 | 
             
                        retVal = HTTParty.get(log_location + "/log/" + did_hash)
         | 
| 41 42 | 
             
                        if retVal.code != 200
         | 
| 42 43 | 
             
                            msg = retVal.parsed_response("error").to_s rescue 
         | 
| @@ -152,20 +153,23 @@ class Oydid | |
| 152 153 |  | 
| 153 154 | 
             
                def self.dag_update(currentDID, options)
         | 
| 154 155 | 
             
                    i = 0
         | 
| 155 | 
            -
                     | 
| 156 | 
            +
                    doc_location = ""
         | 
| 157 | 
            +
                    initial_did = currentDID["did"].to_s.dup
         | 
| 156 158 | 
             
                    initial_did = initial_did.delete_prefix("did:oyd:")
         | 
| 157 | 
            -
                     | 
| 159 | 
            +
                    if initial_did.include?(LOCATION_PREFIX)
         | 
| 160 | 
            +
                        tmp = initial_did.split(LOCATION_PREFIX)
         | 
| 161 | 
            +
                        initial_did = tmp[0] 
         | 
| 162 | 
            +
                        doc_location = tmp[1]
         | 
| 163 | 
            +
                    end
         | 
| 158 164 | 
             
                    current_public_doc_key = ""
         | 
| 159 165 | 
             
                    verification_output = false
         | 
| 160 166 | 
             
                    currentDID["log"].each do |el|
         | 
| 161 167 | 
             
                        case el["op"]
         | 
| 162 168 | 
             
                        when 2,3 # CREATE, UPDATE
         | 
| 163 169 | 
             
                            currentDID["doc_log_id"] = i
         | 
| 164 | 
            -
             | 
| 165 170 | 
             
                            doc_did = el["doc"]
         | 
| 166 | 
            -
                            doc_location = get_location(doc_did)
         | 
| 167 171 | 
             
                            did_hash = doc_did.delete_prefix("did:oyd:")
         | 
| 168 | 
            -
                            did_hash = did_hash.split( | 
| 172 | 
            +
                            did_hash = did_hash.split(LOCATION_PREFIX).first
         | 
| 169 173 | 
             
                            did10 = did_hash[0,10]
         | 
| 170 174 | 
             
                            doc = retrieve_document_raw(doc_did, did10 + ".doc", doc_location, {})
         | 
| 171 175 | 
             
                            if doc.first.nil?
         | 
| @@ -217,9 +221,8 @@ class Oydid | |
| 217 221 | 
             
                            currentDID["termination_log_id"] = i
         | 
| 218 222 |  | 
| 219 223 | 
             
                            doc_did = currentDID["did"]
         | 
| 220 | 
            -
                            doc_location = get_location(doc_did)
         | 
| 221 224 | 
             
                            did_hash = doc_did.delete_prefix("did:oyd:")
         | 
| 222 | 
            -
                            did_hash = did_hash.split( | 
| 225 | 
            +
                            did_hash = did_hash.split(LOCATION_PREFIX).first
         | 
| 223 226 | 
             
                            did10 = did_hash[0,10]
         | 
| 224 227 | 
             
                            doc = retrieve_document_raw(doc_did, did10 + ".doc", doc_location, {})
         | 
| 225 228 | 
             
                            # since it retrieves a DID that previously existed, this test is not necessary
         | 
| @@ -230,11 +233,11 @@ class Oydid | |
| 230 233 | 
             
                            # end
         | 
| 231 234 | 
             
                            doc = doc.first["doc"]
         | 
| 232 235 | 
             
                            term = doc["log"]
         | 
| 233 | 
            -
                            log_location = term.split( | 
| 236 | 
            +
                            log_location = term.split(LOCATION_PREFIX)[1] rescue ""
         | 
| 234 237 | 
             
                            if log_location.to_s == ""
         | 
| 235 238 | 
             
                                log_location = DEFAULT_LOCATION
         | 
| 236 239 | 
             
                            end
         | 
| 237 | 
            -
                            term = term.split( | 
| 240 | 
            +
                            term = term.split(LOCATION_PREFIX).first
         | 
| 238 241 | 
             
                            if hash(canonical(el)) != term
         | 
| 239 242 | 
             
                                currentDID["error"] = 1
         | 
| 240 243 | 
             
                                currentDID["message"] = "Log reference and record don't match"
         | 
| @@ -256,7 +259,7 @@ class Oydid | |
| 256 259 | 
             
                            # check if there is a revocation entry
         | 
| 257 260 | 
             
                            revocation_record = {}
         | 
| 258 261 | 
             
                            revoc_term = el["doc"]
         | 
| 259 | 
            -
                            revoc_term = revoc_term.split( | 
| 262 | 
            +
                            revoc_term = revoc_term.split(LOCATION_PREFIX).first
         | 
| 260 263 | 
             
                            revoc_term_found = false
         | 
| 261 264 | 
             
                            log_array, msg = retrieve_log(did_hash, did10 + ".log", log_location, options)
         | 
| 262 265 | 
             
                            log_array.each do |log_el|
         | 
| @@ -321,9 +324,9 @@ class Oydid | |
| 321 324 | 
             
                                                    currentDID["verification"] += "of next DID Document (Details: https://ownyourdata.github.io/oydid/#verify_signature)" + "\n"
         | 
| 322 325 |  | 
| 323 326 | 
             
                                                    next_doc_did = log_el["doc"].to_s
         | 
| 324 | 
            -
                                                    next_doc_location =  | 
| 327 | 
            +
                                                    next_doc_location = doc_location
         | 
| 325 328 | 
             
                                                    next_did_hash = next_doc_did.delete_prefix("did:oyd:")
         | 
| 326 | 
            -
                                                    next_did_hash = next_did_hash.split( | 
| 329 | 
            +
                                                    next_did_hash = next_did_hash.split(LOCATION_PREFIX).first
         | 
| 327 330 | 
             
                                                    next_did10 = next_did_hash[0,10]
         | 
| 328 331 | 
             
                                                    next_doc = retrieve_document_raw(next_doc_did, next_did10 + ".doc", next_doc_location, {})
         | 
| 329 332 | 
             
                                                    if next_doc.first.nil?
         | 
| @@ -342,9 +345,9 @@ class Oydid | |
| 342 345 | 
             
                                                currentDID["message"] = "Signature does not match"
         | 
| 343 346 | 
             
                                                if verification_output
         | 
| 344 347 | 
             
                                                    new_doc_did = log_el["doc"].to_s
         | 
| 345 | 
            -
                                                    new_doc_location =  | 
| 348 | 
            +
                                                    new_doc_location = doc_location
         | 
| 346 349 | 
             
                                                    new_did_hash = new_doc_did.delete_prefix("did:oyd:")
         | 
| 347 | 
            -
                                                    new_did_hash = new_did_hash.split( | 
| 350 | 
            +
                                                    new_did_hash = new_did_hash.split(LOCATION_PREFIX).first
         | 
| 348 351 | 
             
                                                    new_did10 = new_did_hash[0,10]
         | 
| 349 352 | 
             
                                                    new_doc = retrieve_document(new_doc_did, new_did10 + ".doc", new_doc_location, {}).first
         | 
| 350 353 | 
             
                                                    currentDID["verification"] += "found UPDATE log record:" + "\n"
         | 
    
        data/lib/oydid.rb
    CHANGED
    
    | @@ -2,6 +2,7 @@ | |
| 2 2 | 
             
            # frozen_string_literal: true
         | 
| 3 3 |  | 
| 4 4 | 
             
            require 'dag'
         | 
| 5 | 
            +
            require 'jwt'
         | 
| 5 6 | 
             
            require 'rbnacl'
         | 
| 6 7 | 
             
            require 'ed25519'
         | 
| 7 8 | 
             
            require 'httparty'
         | 
| @@ -11,6 +12,7 @@ require 'multicodecs' | |
| 11 12 | 
             
            require 'json/canonicalization'
         | 
| 12 13 | 
             
            require 'oydid/basic'
         | 
| 13 14 | 
             
            require 'oydid/log'
         | 
| 15 | 
            +
            require 'oydid/didcomm'
         | 
| 14 16 |  | 
| 15 17 | 
             
            class Oydid
         | 
| 16 18 |  | 
| @@ -137,6 +139,11 @@ class Oydid | |
| 137 139 | 
             
                    return write(content, did, "update", options)
         | 
| 138 140 | 
             
                end
         | 
| 139 141 |  | 
| 142 | 
            +
                def self.simulate_did(content, did, mode, options)
         | 
| 143 | 
            +
                    user_did, didDocument, revoc_log, l1, l2, r1, privateKey, revocationKey, did_old, log_old, msg = Oydid.generate_base(content, did, mode, options)
         | 
| 144 | 
            +
                    return [user_did, msg]
         | 
| 145 | 
            +
                end
         | 
| 146 | 
            +
                
         | 
| 140 147 | 
             
                def self.generate_base(content, did, mode, options)
         | 
| 141 148 | 
             
                    # input validation
         | 
| 142 149 | 
             
                    did_doc = JSON.parse(content.to_json) rescue nil
         | 
| @@ -147,7 +154,7 @@ class Oydid | |
| 147 154 | 
             
                    log_old = nil
         | 
| 148 155 | 
             
                    prev_hash = []
         | 
| 149 156 | 
             
                    revoc_log = nil
         | 
| 150 | 
            -
                    doc_location = options[: | 
| 157 | 
            +
                    doc_location = options[:location]
         | 
| 151 158 | 
             
                    if options[:ts].nil?
         | 
| 152 159 | 
             
                        ts = Time.now.to_i
         | 
| 153 160 | 
             
                    else
         | 
| @@ -670,14 +677,13 @@ class Oydid | |
| 670 677 | 
             
                    wd = {}
         | 
| 671 678 | 
             
                    wd["@context"] = "https://www.w3.org/ns/did/v1"
         | 
| 672 679 | 
             
                    wd["id"] = did
         | 
| 673 | 
            -
                    wd[" | 
| 674 | 
            -
                        "id": did,
         | 
| 680 | 
            +
                    wd["verificationMethod"] = [{
         | 
| 681 | 
            +
                        "id": did + "#key-doc",
         | 
| 675 682 | 
             
                        "type": "Ed25519VerificationKey2020",
         | 
| 676 683 | 
             
                        "controller": did,
         | 
| 677 684 | 
             
                        "publicKeyMultibase": pubDocKey
         | 
| 678 | 
            -
                    } | 
| 679 | 
            -
             | 
| 680 | 
            -
                        "id": did,
         | 
| 685 | 
            +
                    },{
         | 
| 686 | 
            +
                        "id": did + "#key-rev",
         | 
| 681 687 | 
             
                        "type": "Ed25519VerificationKey2020",
         | 
| 682 688 | 
             
                        "controller": did,
         | 
| 683 689 | 
             
                        "publicKeyMultibase": pubRevKey
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: oydid
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.4. | 
| 4 | 
            +
              version: 0.4.4
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Christoph Fabianek
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022- | 
| 11 | 
            +
            date: 2022-08-22 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: dag
         | 
| @@ -24,6 +24,20 @@ dependencies: | |
| 24 24 | 
             
                - - "~>"
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 26 | 
             
                    version: 0.0.9
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: jwt
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: 2.4.1
         | 
| 34 | 
            +
              type: :runtime
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: 2.4.1
         | 
| 27 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 42 | 
             
              name: rbnacl
         | 
| 29 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -148,6 +162,7 @@ files: | |
| 148 162 | 
             
            - VERSION
         | 
| 149 163 | 
             
            - lib/oydid.rb
         | 
| 150 164 | 
             
            - lib/oydid/basic.rb
         | 
| 165 | 
            +
            - lib/oydid/didcomm.rb
         | 
| 151 166 | 
             
            - lib/oydid/log.rb
         | 
| 152 167 | 
             
            - spec/input/basic/arrays.json
         | 
| 153 168 | 
             
            - spec/input/basic/french.json
         |