none
Signature fields not well formed. while creating a signature and accessing the BLOB RRS feed

  • Question

  • I have used the following code units to generate the SAS Signature and access the blob. 

                    

        public static String getHMAC256(String key, String input) {
            Mac sha256_HMAC = null;
            String hash = null;
            try {
                sha256_HMAC = Mac.getInstance("HmacSHA256");
                //SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
                SecretKeySpec secret_key = new SecretKeySpec(Base64.getDecoder().decode(key), "HmacSHA256");

                sha256_HMAC.init(secret_key);
                Encoder encoder = Base64.getEncoder();

                hash = new String(encoder.encode(sha256_HMAC.doFinal(input.getBytes("UTF-8"))));

            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            return hash;
        }
                                                                                                                           

    Code to Generate the final URL to access the URL

        public static String getSASToken(String resourceUri, String accountName, String accountKey )
        {

    OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(2);
    OffsetDateTime startTime = OffsetDateTime.now();


    String signedpermissions ="r";
    String signedservice = "b";  
    String signedresourcetype = "o";  
    //String signedstart = "2020-03-28T12:47:38.43Z";  
    //String signedexpiry = "2020-03-30T12:47:38.43Z";
    String signedIP = "";  
    String signedProtocol = "https";
    String signedversion ="2020-02-02";  

    String startTimeText = startTime.format(DateTimeFormatter.ISO_DATE_TIME);
    String expiryTimeText = expiryTime.format(DateTimeFormatter.ISO_DATE_TIME); 

    System.out.println("start="+startTimeText+" Expiry="+expiryTimeText);

    String stringToSign = accountName + "\n" +  
        signedpermissions + "\n" +  
        signedservice + "\n" +  
        signedresourcetype + "\n" +  
        startTimeText + "\n" +  
        expiryTimeText + "\n" +  
        signedProtocol + "\n" +  
        signedversion + "\n"  
        ;

    System.out.println("signature="+stringToSign);

    String signature = getHMAC256(accountKey, stringToSign);

    String sasToken = "";
    try {       
    sasToken = "sv="+signedversion+
    "&ss="+signedservice+
    "&srt="+signedresourcetype+
    "&sp="+signedpermissions+
    "&st=" +URLEncoder.encode(startTimeText, "UTF-8")+
    "&se=" +URLEncoder.encode(expiryTimeText, "UTF-8")+
    "&spr="+signedProtocol+
                        "&sig=" + URLEncoder.encode(signature, "UTF-8");
    sasToken = resourceUri+"?"+sasToken;
    System.out.println(sasToken);       

            } catch (UnsupportedEncodingException e) {

                e.printStackTrace();
            }

            return sasToken;
        }

    I always get the error Fields not well formed. Absolutely no idea as to how do I resolve this. 

    I am using JDK 1.8 with following Maven setup 

    <dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-storage-blob</artifactId>
    <version>12.5.0</version>
    </dependency>

    Saturday, March 28, 2020 9:52 AM

Answers

  • I was able to resolve the issue as follows, I understand there are lots of changes done in 12.5 release. 

    try {
     //Authenticate 
        StorageSharedKeyCredential credential = new StorageSharedKeyCredential(this.getAzureAccountName(), this.getAzureAccountKey());
       
    //Get the Blob Service Client 
        BlobServiceClient client = new BlobServiceClientBuilder()
                .endpoint(this.getAzureEndPoint())
                .credential(credential)
                .buildClient();

        //Get the blobContainerClient
        BlobContainerClient blobContainerClient = 
        blobServiceClient.get().getBlobContainerClient(containerName);
               
            BlockBlobClient blockBlobClient = blobContainerClient
            .getBlobClient(bolbName)
            .getBlockBlobClient();
           
    //Setting Account Permission
                AccountSasPermission permissions = new AccountSasPermission()
                        .setListPermission(true)
                        .setReadPermission(true);
                
    //Following line is required if signature to be generated at container level
                //AccountSasResourceType resourceTypes = new AccountSasResourceType().setContainer(true);

    //In case you want to generate the signature at the object level use 
    AccountSasResourceType resourceTypes = new AccountSasResourceType().setObject(true);

                AccountSasService services = new AccountSasService().setBlobAccess(true).setFileAccess(true);

    //Valid for 2 days starting today
                OffsetDateTime expiryTime = OffsetDateTime.now().plus(Duration.ofDays(2));

                AccountSasSignatureValues sasValues =
                        new AccountSasSignatureValues(expiryTime, permissions, services, resourceTypes);

                String sasToken = blobServiceClient.get().generateAccountSas(sasValues);
            sasToken = blockBlobClient.getBlobUrl()+"?"+sasToken;
            System.out.println("URL to get view the Blob in Browser "+sasToken); 
       
        } catch (Exception e) {
        log.error("Error = {}",e.getMessage());
        }
        }
     
    Tuesday, March 31, 2020 7:08 AM

All replies

  • @INSRATH Firstly, apologies for the delay in responding here and any inconvenience this issue may have caused.  Can you share the screen shot of the error message?

    You may also refer to the suggestion mentioned in the SO  and GitHub thread there is similar discussion on SAS signature fields not well formed, which gives you some idea on your query.

    Kindly let us know if the above helps or you need further assistance on this issue.

    ------------------------------------------------------------------------------------------

    Do click on "Mark as Answer" on the post that helps you, this can be beneficial to other community members.

    Monday, March 30, 2020 10:24 AM
    Moderator
  • I was able to resolve the issue as follows, I understand there are lots of changes done in 12.5 release. 

    try {
     //Authenticate 
        StorageSharedKeyCredential credential = new StorageSharedKeyCredential(this.getAzureAccountName(), this.getAzureAccountKey());
       
    //Get the Blob Service Client 
        BlobServiceClient client = new BlobServiceClientBuilder()
                .endpoint(this.getAzureEndPoint())
                .credential(credential)
                .buildClient();

        //Get the blobContainerClient
        BlobContainerClient blobContainerClient = 
        blobServiceClient.get().getBlobContainerClient(containerName);
               
            BlockBlobClient blockBlobClient = blobContainerClient
            .getBlobClient(bolbName)
            .getBlockBlobClient();
           
    //Setting Account Permission
                AccountSasPermission permissions = new AccountSasPermission()
                        .setListPermission(true)
                        .setReadPermission(true);
                
    //Following line is required if signature to be generated at container level
                //AccountSasResourceType resourceTypes = new AccountSasResourceType().setContainer(true);

    //In case you want to generate the signature at the object level use 
    AccountSasResourceType resourceTypes = new AccountSasResourceType().setObject(true);

                AccountSasService services = new AccountSasService().setBlobAccess(true).setFileAccess(true);

    //Valid for 2 days starting today
                OffsetDateTime expiryTime = OffsetDateTime.now().plus(Duration.ofDays(2));

                AccountSasSignatureValues sasValues =
                        new AccountSasSignatureValues(expiryTime, permissions, services, resourceTypes);

                String sasToken = blobServiceClient.get().generateAccountSas(sasValues);
            sasToken = blockBlobClient.getBlobUrl()+"?"+sasToken;
            System.out.println("URL to get view the Blob in Browser "+sasToken); 
       
        } catch (Exception e) {
        log.error("Error = {}",e.getMessage());
        }
        }
     
    Tuesday, March 31, 2020 7:08 AM
  • Glad to hear that issue got fixed. Appreciate for sharing the steps which helped you, this would certainly benefit other community members

    Tuesday, March 31, 2020 12:05 PM
    Moderator