I'm planning to use the KeyStore in my Android app to encrypt an AES key with a KeyPair that's stored inside the KeyStore. Android documentation for the KeyStore:
https://developer.android.com/training/articles/keystore.html
After searching the internet I found an AOSP example which I edited to this:
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.security.KeyPairGeneratorSpec;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableEntryException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.security.auth.x500.X500Principal;
/**
* Wraps {#link SecretKey} instances using a public/private key pair stored in
* the platform {#link KeyStore}. This allows us to protect symmetric keys with
* hardware-backed crypto, if provided by the device.
* <p>
* See key wrapping for more
* details.
* <p>
* Not inherently thread safe.
*
* Some explanations:
* http://nelenkov.blogspot.nl/2013/08/credential-storage-enhancements-android-43.html
*/
public class SecretKeyWrapper {
private final Cipher mCipher;
private final KeyPair mPair;
/**
* Create a wrapper using the public/private key pair with the given alias.
* If no pair with that alias exists, it will be generated.
*/
public SecretKeyWrapper(Context context, String alias)
throws GeneralSecurityException, IOException {
mCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
final KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
if (!keyStore.containsAlias(alias)) {
generateKeyPair(context, alias);
}
// Even if we just generated the key, always read it back to ensure we
// can read it successfully.
final KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(
alias, null);
mPair = new KeyPair(entry.getCertificate().getPublicKey(), entry.getPrivateKey());
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private static void generateKeyPair(Context context, String alias)
throws GeneralSecurityException {
final Calendar start = new GregorianCalendar();
final Calendar end = new GregorianCalendar();
end.add(Calendar.YEAR, 100);
final KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
.setAlias(alias)
.setSubject(new X500Principal("CN=" + alias))
.setSerialNumber(BigInteger.ONE)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
final KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
gen.initialize(spec);
gen.generateKeyPair();
}
/**
* Wrap a {#link SecretKey} using the public key assigned to this wrapper.
* Use {#link #unwrap(byte[])} to later recover the original
* {#link SecretKey}.
*
* #return a wrapped version of the given {#link SecretKey} that can be
* safely stored on untrusted storage.
*/
public byte[] wrap(SecretKey key) throws GeneralSecurityException {
mCipher.init(Cipher.WRAP_MODE, mPair.getPublic());
return mCipher.wrap(key);
}
/**
* Unwrap a {#link SecretKey} using the private key assigned to this
* wrapper.
*
* #param blob a wrapped {#link SecretKey} as previously returned by
* {#link #wrap(SecretKey)}.
*/
public SecretKey unwrap(byte[] blob) throws GeneralSecurityException {
mCipher.init(Cipher.UNWRAP_MODE, mPair.getPrivate());
return (SecretKey) mCipher.unwrap(blob, "AES", Cipher.SECRET_KEY);
}
}
This implementation kan wrap and unwrap a SecretKey which is in my case an AES key.
However, this KeyStore is only supported from 4.3 and onwards. See the Jelly Bean annotation.
To come to my question, what are the possibilities for a likewise implementation for below 4.3?
Thanks in advance,
The keystore is available since 1.6, but there is no official API in earlier versions. You can still use it through the private API, but you might face various problems.
An example can be found on the same blog you referenced:
http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html
The implementation might end up somewhat tricky because the keystore needs to be unlocked independently from the device lockscreen. It might be better to consider password-based encryption for earlier versions, there is a post about it on the blog.
Symmetric key generation and storage in the Android KeyStore is supported from Android 6.0 (API Level 23) onwards.
Asymmetric key generation and storage in the Android KeyStore is supported from Android 4.3 (API Level 18) onwards.
See this document for more info:
http://developer.android.com/training/articles/keystore.html
Related
I need to connect to Google Cloud Firestore from my Next.js serverless function hosted in Vercel. I already have a service account set up, but all the docs out there rely on the credentials being a file, while I'd like to use environment variables (more natural in Vercel platform).
Example:
const Firestore = require('#google-cloud/firestore');
const firestore = new Firestore({
projectId: 'YOUR_PROJECT_ID',
keyFilename: '/path/to/keyfile.json',
});
I cannot use keyFilename, I'd rather pass the service account email and private key explicitly.
Working code:
const projectId = process.env.GOOGLE_PROJECT_ID;
const email = process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL;
const key = process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n');
const Firestore = require('#google-cloud/firestore');
const firestore = new Firestore({
projectId: projectId,
credentials: {
client_email: email,
private_key: key,
},
});
Please note that my GOOGLE_PRIVATE_KEY env var has literal \ns, exactly as Google Cloud's JSON comes, so I use .replace() on it to translate them to actual newlines. This is actually only needed in my local environment, where I use .env.local, since Vercel env vars can take actual newlines.
Source
The settings object (argument for the constructor Firestore()) is poorly documented, but I was able to figure it out by myself grepping through the source code, where I found:
node_modules/#google-cloud/firestore/types/firestore.d.ts
Line 217:
/**
* Settings used to directly configure a `Firestore` instance.
*/
export interface Settings {
/**
* The project ID from the Google Developer's Console, e.g.
* 'grape-spaceship-123'. We will also check the environment variable
* GCLOUD_PROJECT for your project ID. Can be omitted in environments that
* support {#link https://cloud.google.com/docs/authentication Application
* Default Credentials}
*/
projectId?: string;
/** The hostname to connect to. */
host?: string;
/** The port to connect to. */
port?: number;
/**
* Local file containing the Service Account credentials as downloaded from
* the Google Developers Console. Can be omitted in environments that
* support {#link https://cloud.google.com/docs/authentication Application
* Default Credentials}. To configure Firestore with custom credentials, use
* the `credentials` property to provide the `client_email` and
* `private_key` of your service account.
*/
keyFilename?: string;
/**
* The 'client_email' and 'private_key' properties of the service account
* to use with your Firestore project. Can be omitted in environments that
* support {#link https://cloud.google.com/docs/authentication Application
* Default Credentials}. If your credentials are stored in a JSON file, you
* can specify a `keyFilename` instead.
*/
credentials?: {client_email?: string; private_key?: string};
/** Whether to use SSL when connecting. */
ssl?: boolean;
/**
* The maximum number of idle GRPC channels to keep. A smaller number of idle
* channels reduces memory usage but increases request latency for clients
* with fluctuating request rates. If set to 0, shuts down all GRPC channels
* when the client becomes idle. Defaults to 1.
*/
maxIdleChannels?: number;
/**
* Whether to use `BigInt` for integer types when deserializing Firestore
* Documents. Regardless of magnitude, all integer values are returned as
* `BigInt` to match the precision of the Firestore backend. Floating point
* numbers continue to use JavaScript's `number` type.
*/
useBigInt?: boolean;
/**
* Whether to skip nested properties that are set to `undefined` during
* object serialization. If set to `true`, these properties are skipped
* and not written to Firestore. If set `false` or omitted, the SDK throws
* an exception when it encounters properties of type `undefined`.
*/
ignoreUndefinedProperties?: boolean;
[key: string]: any; // Accept other properties, such as GRPC settings.
}
when creating a new script in unity I have a script that changes various pieces of information generating the copyright information attached to the file, however while most information is either static or procedurally determined the name of the active programmer can't be determined in either way, I am trying to show a popup before the asset is actually created asking for the name of the developer but my current method provides only an error, is there a way around this?
using UnityEngine;
using UnityEditor;
/* Project Name : Project Venom
* Script Name : ScriptKeywordProcessor
* Script Path : /Editor/ScriptKeywordProcessor.cs
* Script Author : FaalFaazDov || Raistlin M. Thoreson
* Created On : 08/29/2016 12:46
* Modified On : 09/28/2016 18:25
* Version : 1.1.0
*/
/*************************************************************************
*
* Biophase Entertainment
* __________________
*
* [2016] Biophase Entertainment
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Biophase Entertainment and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Biophase Entertainment
* and its suppliers and may be covered by Canadian and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information, reproduction of this material or attempting
* to read the content of these files is strictly forbidden unless prior written
* permission is obtained from Biophase Entertainment.
*
*/
internal sealed class ScriptKeywordProcessor : UnityEditor.AssetModificationProcessor {
public string DeveloperName = "";
public static void OnWillCreateAsset(string path) {
EditorWindow window = EditorWindow.CreateInstance<ScriptKeywordProcessor> ();
window.Show ();
}
void OnGUI() {
GUILayout.Label ("Developer Name", EditorStyles.boldLabel);
DeveloperName = GUILayout.TextField (DeveloperName, 100);
}
}
the error I am recieving is
Assets/Editor/ScriptKeywordProcessor.cs(39,38): error CS0309: The type
ScriptKeywordProcessor must be convertible to
UnityEngine.ScriptableObject in order to use it as parameter T in
the generic type or method
UnityEngine.ScriptableObject.CreateInstance<T>()
From your code, the ScriptKeywordProcessor is not an EditorWindow which is inherited from ScriptableObject.
You need to define another class inherited from EditorWindow to do GUI works. Then open your window in the OnWillCreateAsset method of ScriptKeywordProcessor.
I use Acceleo in order to generate code with a model I have made. I managed to protect my methods in order to protect them usinig "#generated NOT" in case I need to regenerate my code with Acceleo. The problem is that adding #generated NOT protect all the method content, that is to say the body, the signature and JavaDocs.
The thing is that I only need to keep the method body, or at least the method body and its signature, but I need the doc to be updated. How can I do this ?
Just for information here is an example of a potential generated class :
/*
* #generated
*/
public class ActeurRefEntrepriseServicesImpl implements ActeurRefEntrepriseServices {
#Autowired
HelloWorldService helloWorldService;
/**
* Service which say hello
*
* #param name
* user name
* #return print Hello username
*
* #generated NOT
*/
#Override
public void sayHello(final String name) {
helloWorldService.print(name);
}
}
Baptiste,
The #generated tags use the standard EMF protection rules : "#generated" means that the body of the block for which it is set will be generated, anything else means no re-generation. If you set something as "#generated" in any of your metamodels' generated code, you will see that there, too, the javadoc is preserved whatever the edits you do.
In short, you cannot tell EMF to re-generate anything other than the code itself.
If you need to have the body protected but not the javadoc, you have to shift from the "#generated" protection to Acceleo's [protected] blocks. i.e, change your template from :
[template generatedMethod(methodName : String)]
/**
* Some doc.
* #param param1
* param documentation.
* #generated
*/
[generateSignature(methodName)/] {
[generateBody()/]
}
[/template]
to something using a protected block :
[template generatedMethod(methodName : String)]
/**
* Some doc.
* #param param1
* param documentation.
*/
[protected (methodName)]
[generateSignature(methodName)/] {
[generateBody()/]
}
[/protected]
[/template]
With this paradigm, anything that is outside of the protected area will be regenerated, everything else will remain untouched by a regeneration.
See also the full documentation available from the Acceleo website.
If you absolutely need to use the "#generated" protection method for your model, you will need to tamper with the JMerger API from EMF and alter the launcher Acceleo generated for you in order to use your own merging strategy (see the getGenerationStrategy method from that launcher). Note that this is by no means an easy task.
We've developed a custom plugin for Notes 8.5.2. It records a number of custom user preferences. The class that does so is shown below:
import java.util.prefs.Preferences;
/**
* Provides programmatic access to Windows Registry entries for this plug-in.
*/
public class Registry
{
Preferences prefs;
/**
* Initializes a new instance of the Registry class.
*/
public Registry()
{
prefs = Preferences.userNodeForPackage(Registry.class) ;
}
/**
* Gets the value of a registry key.
*
* #param keyName The name of the key to return.
*
* #return A string containing the value of the specified registry key. If a key with the specified name cannot be
* found, the return value is an empty string.
*/
public String GetValue(String keyName)
{
try
{
return prefs.get(keyName, "NA") ;
}
catch(Exception err)
{
return "" ;
}
}
/**
* Sets the value of a registry key.
*
* #param keyName The name of the registry key.
*
* #param keyValue The new value for the registry key.
*/
public void SetValue(String keyName, String keyValue)
{
try
{
prefs.put(keyName, keyValue);
prefs.flush();
}
catch(Exception err)
{
}
}
}
A sample of the code that uses it is as follows:
Registry wr = new Registry();
String setting1 = wr.GetValue("CustomSetting1");
wr.SetValue("CustomSetting1", newValue);
Now, I've scanned the Windows Registry, and these settings do not exist. I've indexed my entire hard disk, and I cannot find these entries in any file.
So, where the heck are these settings being stored?
On Windows the Java Preferences API uses the Registry as it's backing store for the Preferences class. The keys are rooted by package name under HKEY_CURRENT_USER\Software\JavaSoft\Prefs.
Your code doesn't specify a package, so it uses the following location by default (tested on Windows Vista and 7):
HKEY_CURRENT_USER\Software\JavaSoft\Prefs\<unnamed>
There is an articled titled "Sir, What is Your Preference?" by Ray Djajadinataz at the Sun Developer Network where you can get a little more background on this API with some screen shots showing registry locations.
I wonder if you were searching for the key name, eg CustomSetting1, and not finding it because it is saved as /Custom/Setting1 to note that the C and S are capitalized (see API docs.)
At the moment we're going to migrating all of our cvs projects to git.
Our custom script is using the git converter and everything is fine.
Now i would like to incorporate the automated replacement of the scm part
properties with the new values.
Is there a plugin similar to org.codehaus.mojo:versions-maven-plugin but appling to the scm part?
No, but it would be a trivial plugin to implement.
Just define search and replace patterns:
/**
* #parameter expression="${project}"
* #readonly
*/
private MavenProject project;
/**
* #parameter expression="${searchPattern}"
* #required
*/
private String searchPattern;
/**
* #parameter expression="${replacePattern}"
* #required
*/
private String replacePattern;
/**
* #component
*/
private ModelWriter modelWriter;
public void execute(){
final Model model = project.getModel();
model.getScm().setConnection(
model.getScm()
.getConnection()
.replaceFirst(searchPattern, replacePattern));
// do the same for scm.getDeveloperConnection()
modelWriter.write(
new File(project.getBasedir(),"pom.xml"),
Collections.<String,Object>emptyMap(), model);
}
No there is no plugin for this kind of purpose. (May be someone else knows one?)