如何在Java客户端使用serviceAccounts.keys.create API生成的Google云平台服务帐户密钥?

如何在Java客户端使用serviceAccounts.keys.create API生成的Google云平台服务帐户密钥?,java,google-app-engine,google-cloud-storage,google-api-java-client,service-accounts,Java,Google App Engine,Google Cloud Storage,Google Api Java Client,Service Accounts,我正在使用GAE中生成的服务帐户密钥,使用客户端的servicecomports.keys.createGoogle IAM API将文件上载到GCS。此API返回我在客户端代码中使用的privateKeyData字段,如下所示: public class GCSTest { public static final String CLOUD_STORAGE_SCOPE = "https://www.googleapis.com/auth/cloud-platfor

我正在使用GAE中生成的服务帐户密钥,使用客户端的
servicecomports.keys.create
Google IAM API将文件上载到GCS。此API返回我在客户端代码中使用的
privateKeyData
字段,如下所示:

public class GCSTest {
    public static final String CLOUD_STORAGE_SCOPE =
            "https://www.googleapis.com/auth/cloud-platform";
    private GoogleCredential credential = null;
    private HttpTransport HTTP_TRANSPORT = null;
    private Storage storage = null;
    private final JsonFactory json_factory = JacksonFactory
            .getDefaultInstance();
    public String APPLICATION_NAME = "GCSTest";
    private String privKeyString =
            <copy the privateKeyData from response of serviceAccounts.keys.create>;

    public void startTests() {
        initStorageService();
        writeObject();
    }

    private void initStorageService() {
        List<String> scopeList = new ArrayList<String>();
        scopeList.add(CLOUD_STORAGE_SCOPE);
        HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

        byte[] privKeyBytes = Base64.decodeBase64(privKeyString.getBytes());
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privKeyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = kf.generatePrivate(spec);
        credential =
            new GoogleCredential.Builder()
                .setTransport(HTTP_TRANSPORT)
                .setJsonFactory(json_factory)
                .setServiceAccountId(
                        "<service_account_name>@<project-id>.iam.gserviceaccount.com")
                .setServiceAccountScopes(scopeList)
                .setServiceAccountPrivateKey(privateKey)
                .setServiceAccountPrivateKeyId(
                        "<key_id>")
                .build();

        storage =
            new Storage.Builder(HTTP_TRANSPORT, json_factory,
                credential).setApplicationName(APPLICATION_NAME)
                .build();
    }
    private void writeObject() {
        String fileName = "StorageSample";
        Path tempPath = Files.createTempFile(fileName, ".txt");;
        Files.write(tempPath, "Sample file".getBytes());
        File tempFile = tempPath.toFile();
        tempFile.deleteOnExit();

        InputStreamContent contentStream =
                new InputStreamContent("text/plain", new FileInputStream(
                        tempFile));
        contentStream.setLength(tempFile.length());
        StorageObject objectMetadata = new StorageObject().setName(fileName);
        Storage.Objects.Insert insert = 
            storage.objects().insert(<bucket_name>,
                        objectMetadata, contentStream);;
        insert.setName(fileName);
        insert.execute();
    }
}
公共类GCSTest{
公共静态最终字符串云存储范围=
"https://www.googleapis.com/auth/cloud-platform";
私有Google凭证凭证=null;
私有HttpTransport HTTP_TRANSPORT=null;
私有存储=null;
私有最终JsonFactory json_factory=JacksonFactory
.getDefaultInstance();
公共字符串应用程序\u NAME=“GCSTest”;
私有字符串privKeyString=
;
公共无效开始测试(){
initStorageService();
writeObject();
}
私有存储服务(){
List scopeList=new ArrayList();
scopeList.add(云存储范围);
HTTP_TRANSPORT=GoogleNetHttpTransport.newTrustedTransport();
byte[]privKeyBytes=Base64.decodeBase64(privKeyString.getBytes());
PKCS8EncodedKeySpec spec=新的PKCS8EncodedKeySpec(privKeyBytes);
KeyFactory kf=KeyFactory.getInstance(“RSA”);
PrivateKey PrivateKey=kf.generatePrivate(规范);
凭证=
新建GoogleCredential.Builder()
.setTransport(HTTP_传输)
.setJsonFactory(json_工厂)
.SetServiceAccounted(
“@.iam.gserviceaccount.com”)
.setServiceAccountScopes(范围列表)
.setServiceAccountPrivateKey(privateKey)
.setServiceAccountPrivateKeyId(
"")
.build();
储藏=
new Storage.Builder(HTTP_传输、json_工厂、,
凭证).setApplicationName(应用程序名称)
.build();
}
私有void writeObject(){
字符串fileName=“StorageSample”;
Path tempPath=Files.createTempFile(文件名“.txt”);;
write(tempPath,“Sample file”.getBytes());
File tempFile=tempPath.toFile();
tempFile.deleteOnExit();
InputStreamContent内容流=
新的InputStreamContent(“文本/普通”,新文件InputStream(
临时文件);
setLength(tempFile.length());
StorageObject objectMetadata=新的StorageObject().setName(文件名);
Storage.Objects.Insert=
storage.objects().insert(,
对象元数据(contentStream);;
插入.setName(文件名);
insert.execute();
}
}
但是,当调用
storage.objects().insert
时,我得到
java.security.InvalidKeyException:invalid key format exception
。 这是使用服务帐户密钥生成
GoogleCredential
的正确方法吗?
我知道JSON或P12密钥文件。我不想使用它,因为它不适合我的用例。

默认情况下,
servicecomports.keys.create
生成一个GOOGLE\u凭证文件,它是一个描述密钥和其他内容的JSON文档。像这样的客户端可以读取这些文件,如下所示:

StorageOptions options = StorageOptions.builder().projectId(PROJECT_ID)
    .authCredentials(AuthCredentials.createForJson(
          new FileInputStream(PATH_TO_JSON_KEY))).build();
Storage service = options.service();

但是,您的代码需要一个p12密钥文件。您可以将JSON文件中的密钥提取为这样的格式,但更简单的方法可能是调用
servicecomports.keys.create
,将
servicecomportprivatekey
参数设置为
TYPE\u PKCS12\u FILE

结果是使用
servicecomports.keys.create
生成的私钥字符串的密码是
notacret
。以下代码从API响应的
privateKeyData
字段中获取
PrivateKey
。此
PrivateKey
可用于获取
GoogleCredential

byte[] privKeyBytes = Base64.decodeBase64(privKeyString.getBytes());
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new ByteArrayInputStream(privKeyBytes), "notasecret".toCharArray());
PrivateKey privateKey = (PrivateKey) ks.getKey("privatekey", "notasecret".toCharArray());

非常感谢。我使用
TYPE\u PKCS12\u文件
生成了密钥,但现在我得到了
java.security.InvalidKeyException:IOException:version mismatch:(支持:00,解析:03
错误)。