I've stored sound file on IPFS and IPFS hash is connected to ERC721 token.
I want make "only token holder can access the data". But unfortunately data on blockchain and ipfs is public, so everyone can access.
Is there any way to let only token holder can access ipfs data?
My solution does not work...
- Store encrypted data on IPFS and store key on ERC721 token.(If set key as public, every one can see it, and if set key as private no one including token holder can see it)
If you have any suggestion or solution, please guide me!!
This is my product image. I want make this sound token data only available for token owner.
https://medium.com/coinmonks/converting-sound-file-to-erc721-token-with-digital-art-chain-29b1890b6d4d
Have a look at Permissioned Blocks whitepaper - https://github.com/autocontracts/permissioned-blocks/blob/master/whitepaper.md#a-permissioned-file-sharing-model-for-distributed-networks
Following is from the text at the link shared above -
"Combining a peer-to-peer file sharing protocol with a blockchain protocol, a smart contract can be used as the security mechanism for the peer-to-peer file sharing protocol."
A thorough understanding is needed but this could be a good starting point for permissions and access control on IPFS using Ethereum.
No, this will not work with only blockchain and IPFS. Sorry.
You can try this approach:
[ Customer ] --buy---------------> [ blockchain ]
| ^ \ ^
| | \ verify permission
| | \ |
| | \-request access-> [ DRM server ]
| | |
| \-------------- send access hash---/
|
\----access file with access ID-> [ IPFS ]
The customer will request access to the file by signing a message which uses the same account as is recorded on the blockchain.
A material weakness of this approach (and any approach using IPFS) is that anybody that can access the system can also share the files without you knowing. That also means they can share with themselves (i.e. you can't limit time access).
Related
orbitdb says it cant do it https://github.com/orbitdb/field-manual/blob/684c7a1aa427c9acfe4d73cd28d64880e072b086/01_Tutorial/06_Identity_Permission.md#on-security
but users want to give/take writing permissions to dbs
how to implement user model without 3d-party services or ipns?
what to use for user identity?
peer-id and private-key
specifically - of ipfs node - a config json file that node generates
running ipfs init /path/to/config allows to create same node with identity
it is simple - no need for DIDs - it works as SSH keys
ownership
program starts with discovery - users need to be able to discover dbs, like we can discover repos on github
program creates a public orbitdb database anyone can write to
users publish the dbs they want others to see to that list
and - when the write they also write name of db
if same name - how do we now that this db is actually from owner we expect? by peer-id
every message on pubsub - and also orbidb write entries - have peer-id of who posted them
so program shows name of db and peer-id of author - this way we know that that record in discovery db is exactly from that peer
and - as long as config file with peer-id and private-key is not lost - that person owns that identity
how to add/revoke writes in orbitdb without re-creating new db with new id? without 3d party services or ipns?
this is brilliant
an owner - always an owner - wants to give/take permissions
once owner creates db, program also creates a access-cotrol database - a list simply - with write permissions only to owner
other peers clone owner's db - and program also clones access-control db
program implements custom access-controller that reads from access-controller db and checks - is peer listed there? then they can write
no third party anything needed - all is already done within orbitdb
and that access controller list already decentralized and persistent and replicatable
is orbitdb id needed? is orbitb/keystore needed?
no
if program were to use ObritDBAccessController - where permissions are give by orbitdb id - then yes
but it is useless - we can add or revoke
and - as said above - the better solution is access-controll-peer-id-list-db that comes with each database
and for that - custom access-controller is needed
and since we have that - why would we make it use orbitdb identity when peer-id is much better - it is the identity of user, that they can persist and backup and they init ipfs from again
one identity - ipfs node config json file with peer-id and private-key
Hope somebody can get me past this point... because I spend pretty much time on it and still not working.
Short story is that I want to use Azure Notification Hub for my Xamarin.Forms app.
It want's these info to work:
That's all good and I got all of them under control, expect the Token one.
Ok, so I follow the Microsoft docs on the subject:
https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-push-notification-http2-token-authentification
I follow along and got things under controls I think, until I get to:
"Authentication token"
Here it says:
The authentication token can be downloaded after you generate a token for your application. For details on how to generate this token, refer to Appleās Developer documentation.
Like it's no big deal and then it links to this page, which is suppose to help me. Read through it, clicked the links etc. read stuff.
I end up on this page: Establishing a Token-Based Connection to APNs
And the the craziness and confusion really kicks off for me, because, it then says, like it's the most common thing in the world:
Encrypt the resulting JSON data using your authentication token signing key and the specified algorithm
It doesn't really explain much, other than link to the jwt.io tool.
Well, that would have been great if I could make the tool work...
On the surface it's pretty easy, as the docs explains what to put in where, so I do that:
So the "header" and the "payload" is filled in and I assume it's correct - however, at the bottom I clearly need to put in some keys for this to be able to decrypted correctly on the other end...the question what do I put in here?
When I created my key in the Apple Developer portal, I of cause downloded the .p8 file, which I can see contains my PRIVATE key...but I have 2 problems.
Putting that into this jwt.io tool, result in a "invalid signature" right away, and I have no idea what to put into the "PUBLIC KEY" part.
So, what am I doing wrong?
Thanks in advance and really hope somebody can help me, as I'm starting to go crazy over this, "tiny" step in the development that have been taking WAY too long now.
At the bottom of jwt.io there are libraries you can use to encrypt the token on your server. For example, this php library: https://github.com/lcobucci/jwt/blob/3.3/README.md
About public key. I think it's the KeyID that is the public key that APNs uses to verify. You only need the private key to generate the token. It goes like this in this php sample:
$token = (new Builder())->issuedBy('http://example.com') // Configures the issuer (iss claim)
->permittedFor('http://example.org') // Configures the audience (aud claim)
->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item
->issuedAt($time) // Configures the time that the token was issue (iat claim)
->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim)
->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim)
->withClaim('uid', 1) // Configures a new claim, called "uid"
->getToken($signer, $privateKey); // Retrieves the generated token
Just to whoever stumbles upon this question.
The token field in the Azure Notification Hubs Settings is the private key which you will find inside the .p8 file you downloaded from Apple Developer Account for Universal APN.
As for the JWT encryption, you need that when you sending a request to apple's apn server directly. You will need to send a Bearer token by encrypting the header and payload ( specifications are in apple's website). The encryption is done by crypto libraries, using algorithm ES256 ( only one supported for APN ) and the signing key is the token we mentioned above, that is the private key in the .p8. This creates a JWT that you include in your Authorization header for the request to APN server
Using JSON HTTP POST; what online service do I best use to broadcast a Bitcoin Cash transaction?
I'm looking for the equivalent of https://blockchain.info/pushtx
There are a few options to broadcast a transaction for Bitcoin and Bitcoin-Cash. The first, but also the most expensive in terms of time, is to setup a BitcoinABC node on your machine and let it sync. Once that's done you can simply call the sendrawtransaction API call and it'll get pushed to other nodes in the network.
The second option is to use Wladimir's bitcoin-submittx tool to connect to a number of nodes and submit the transaction to them. This tool was originally written for Bitcoin, but works also for Bitcoin-Cash. It requires a number of node addresses, but you can use the DNS seeds to get some:
python2 bitcoin-submittx mainnet ${TXHEX} $(dig seed-abc.bitcoinforks.org)
This should submit the TX to some random nodes in the network.
https://rest.bitcoin.com provides a REST API for broadcasting transactions. This BITBOX code example shows how to construct a BCH transaction then broadcast it using rest.bitcoin.com:
https://github.com/Bitcoin-com/bitbox-javascript-sdk/blob/master/examples/applications/wallet/send-bch/send-bch.js
In particular, look at the last few lines of the example:
// Broadcast transation to the network
const broadcast = await BITBOX.RawTransactions.sendRawTransaction(hex)
console.log(`Transaction ID: ${broadcast}`)
API documentation:
https://developer.bitcoin.com/bitbox/docs/getting-started
If you already have the raw hex and you want a manual way to broadcast it, you can go directly to the endpoint on rest.bitcoin.com, and paste in the hex:
https://rest.bitcoin.com/#/rawtransactions/sendRawTransaction
I'm building an application that stores files into the FIWARE Object Storage. I don't quite understand what is the correct way of storing files into the storage.
The code python code snippet below taken from the Object Storage - User and Programmers Guide shows 2 ways of doing it:
def store_text(token, auth, container_name, object_name, object_text):
headers = {"X-Auth-Token": token}
# 1. version
#body = '{"mimetype":"text/plain", "metadata":{}, "value" : "' + object_text + '"}'
# 2. version
body = object_text
url = auth + "/" + container_name + "/" + object_name
return swift_request('PUT', url, headers, body)
The 1. version confuses me, because when I first looked at the only Node.js module (repo: fiware-object-storage) that works with Object Storage, it seemed to use 1. version. As the module was making calls to the old (v.1.1) API version instead of the presumably newest (v.2.0), referencing to the python example, not sure if that is an outdated version of doing it or not.
As I played more with the module, realised it didn't work and the code for it was a total mess. So I forked the project and quickly understood that I will need rewrite it form the ground up, taking the above mention python example from the usage guide as an reference. Link to my repo.
As of writing this the only methods that aren't implement is the object storage (PUT) and object fetching (GET).
Had some addition questions about the Object Storage which I sent to fiware-lab-help#lists.fiware.org, but haven't heard anything back so asking them here.
Haven't got much experience with writing API libraries. Should I need to worry about auth token expiring? I presume it is not needed to make a new authentication, every time we interact with storage. The authentication should happen once when server is starting-up (we create a instance) and it internally keeps it. Should I implement some kind of mechanism that refreshes the token?
Does the tenant id change? From the quote below is presume that getting a tenant I just a one time deal, then later you can use it in the config to make less authentication calls.
A valid token is required to access an object store. This section
describes how to get a valid token assuming an identity management
system compatible with OpenStack Keystone is being used. If the
username, password and tenant details are known, only step 3 is
required. source
During the authentication when fetching tenants how should I select the "right" one? For now i'm just taking the first one similar as the example code does.
Is it true that a object storage container belongs to only a single region?
Use only what you call version 2. Ignore your version 1. It is commented out in the example. It should be removed from the documentation.
(1) The token will be valid for some period of time. This could be an hour or a day, depending on the setup. This period of time should be specified in the token that is returned by the authentication service. The token needs to be periodically refreshed.
(2) The tenant id does not change.
(3) Typically only one tenant id is returned. It is possible, however, that you were assigned more than one id, in which case you have to pick which one you are currently using. Containers typically belong to a single tenant and are not shared between tenants.
(4) Containers are typically limited to a single region. This may change in the future when multi-region support for a container is added to Swift.
Solved my troubles and created the NPM module that works with the FIWARE Object Storage: https://github.com/renarsvilnis/fiware-object-storage-ge
I've successfully installed and run the Google Drive Quick Start application called DriveCommandLine. I've also adapted it a little to GET file info for one of the files in my Drive account.
What I would like to do now is save the credentials somehow and re-use them without the user having to visit a web page each time to get an authorization code. I have checked out this page with instructions to Retrieve and Use OAuth 2.0 credentials. In order to use the example class (MyClass), I have modified the line in DriveCommandLine where the Credential object is instantiated:
Credential credential = MyClass.getCredentials(code, "");
This results in the following exception being thrown:
java.lang.NullPointerException
at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:187)
at com.google.api.client.json.jackson.JacksonFactory.createJsonParser(JacksonFactory.java:84)
at com.google.api.client.json.JsonFactory.fromInputStream(JsonFactory.java:247)
at com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.load(GoogleClientSecrets.java:168)
at googledrive.MyClass.getFlow(MyClass.java:145)
at googledrive.MyClass.exchangeCode(MyClass.java:166)
at googledrive.MyClass.getCredentials(MyClass.java:239)
at googledrive.DriveCommandLine.<init>(DriveCommandLine.java:56)
at googledrive.DriveCommandLine.main(DriveCommandLine.java:115)
I've been looking at these APIs (Google Drive and OAuth) for 2 days now and have made very little progress. I'd really appreciate some help with the above error and the problem of getting persistent credentials in general.
This whole structure seems unnecessarily complicated to me. Anybody care to explain why I can't just create a simple Credential object by passing in my Google username and password?
Thanks,
Brian O Carroll, Dublin, Ireland
* Update *
Ok, I've just gotten around the above error and now I have a new one.
The way I got around the first problem was by modifying MyClass.getFlow(). Instead of creating a GoogleClientServices object from a json file, I have used a different version of GoogleAuthorizationCodeFlow.Builder that allows you to enter the client ID and client secret directly as Strings:
flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, jsonFactory, "<MY CLIENT ID>", "<MY CLIENT SECRET>", SCOPES).setAccessType("offline").setApprovalPrompt("force").build();
The problem I have now is that I get the following error when I try to use flow (GoogleAuthorizationCodeFlow object) to exchange the authorization code for the Credentials object:
An error occurred: com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_scope"
}
googledrive.MyClass$CodeExchangeException
at googledrive.MyClass.exchangeCode(MyClass.java:185)
at googledrive.MyClass.getCredentials(MyClass.java:262)
at googledrive.DriveCommandLine.<init>(DriveCommandLine.java:56)
at googledrive.DriveCommandLine.main(DriveCommandLine.java:115)
Is there some other scope I should be using for this? I am currently using the array of scopes provided with MyClass:
private static final List<String> SCOPES = Arrays.asList(
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile");
Thanks!
I feel your pain. I'm two months in and still getting surprised.
Some of my learnings...
When you request user permissions, specify "offline=true". This will ("sometimes" sic) return a refreshtoken, which is as good as a password with restricted permissions. You can store this and reuse it at any time (until the user revokes it) to fetch an access token.
My feeling is that the Google SDKs are more of a hinderence than a help. One by one, I've stopped using them and now call the REST API directly.
On your last point, you can (just) use the Google clientlogin protocol to access the previous generation of APIs. However this is totally deprecated and will shortly be turned off. OAuth is designed to give fine grained control of authorisation which is intrinsically complex. So although I agree it's complicated, I don't think it's unnecessarily so. We live in a complicated world :-)
Your and mine experiences show that the development community is still in need of a consolidated document and recipes to get this stuff into our rear-view mirrors so we can focus on the task at hand.
Oath2Scopes is imported as follows:
import com.google.api.services.oauth2.Oauth2Scopes;
You need to have the jar file 'google-api-services-oauth2-v2-rev15-1.8.0-beta.jar' in your class path to access that package. It can be downloaded here.
No, I don't know how to get Credentials without having to visit the authorization URL at least once and copy the code. I've modified MyClass to store and retrieve credentials from a database (in my case, it's a simple table that contains userid, accesstoken and refreshtoken). This way I only have to get the authorization code once and once I get the access/refresh tokens, I can reuse them to make a GoogleCredential object. Here's how Imake the GoogleCredential object:
GoogleCredential credential = new GoogleCredential.Builder().setJsonFactory(jsonFactory)
.setTransport(httpTransport).setClientSecrets(clientid, clientsecret).build();
credential.setAccessToken(accessToken);
credential.setRefreshToken(refreshToken);
Just enter your clientid, clientsecret, accessToken and refreshToken above.
I don't really have a whole lot of time to separate and tidy up my entire code to post it up here but if you're still having problems, let me know and I'll see what I can do. Although, you are effectively asking a blind man for directions. My understanding of this whole system is very sketchy!
Cheers,
Brian
Ok, I've finally solved the second problem above and I'm finally getting a working GoogleCredential object with an access token and a refresh token.
I kept trying to solve the scopes problem by modifying the list of scopes in MyClass (the one that manages credentials). In the end I needed to adjust the scopes in my modified version of DriveCommandLine (the one that's originally used to get an authorization code). I added 2 scopes from Oauth2Scopes:
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET,
Arrays.asList(DriveScopes.DRIVE, Oauth2Scopes.USERINFO_EMAIL, Oauth2Scopes.USERINFO_PROFILE))
.setAccessType("offline").setApprovalPrompt("force").build();
Adding the scopes for user information allowed me to get the userid later in MyClass. I can now use the userid to store the credentials in a database for re-use (without having to get the user to go to a URL each time). I also set the access type to "offline" as suggested by pinoyyid.