Oh, Google Tink, Private Key IDs and Signatures

I have been investing ECDSA signatures and the DER format, and I always found that the DER signature starts with a “30” to identify…

Photo by Romain Dancre on Unsplash

Oh, Google Tink, Private Key IDs and Signatures

I have been investigating ECDSA signatures and the DER format. Overall, in hex format, I always found that the DER signature starts with a “30” — to identify SEQUENCE — and then followed by two integers: r and s. But, when I was updating my Google Java Tink code I found this as a signature [here]:

Signature generator
Text: hello
Type: ECDSA_P256
Sig (Base64): ASZfrgQwRAIgZ7zQ37QHqqMjPMxObgq/58taZWSTrbXUkkyEoamBexICICCACK4t/8ooWS1HhT9BXQpaE6yH70zVDZe0x63O4DEw
Sig (Hex): 01265FAE043044022067BCD0DFB407AAA3233CCC4E6E0ABFE7CB5A656493ADB5D4924C84A1A9817B120220208008AE2DFFCA28592D47853F415D0A5A13AC87EF4CD50D97B4C7ADCEE03130
Valid Signature
Printing out key:
{
"primaryKeyId": 643804676,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey",
"keyMaterialType": "ASYMMETRIC_PRIVATE",
"value": "EkwSBggDEAIYAhogSxH0Ta+brkGS9KTFyqM1i+nn05ukrs4IJZk3OcSNGAsiIAZ+ijm1cI/55L/Ldx0p8+Vo92y5XjMtPqLobyR96tlwGiBtCNp1QkmBTqqW1uiopnQUP2h+SqoEaD31SFBc2YNpFQ=="
},
"outputPrefixType": "TINK",
"keyId": 643804676,
"status": "ENABLED"
}]
}

Everything seemed to be fine, and where I could validate the signature. But I was scratching my head trying to understand the signature format:

Sig (Hex): 01265FAE043044022067BCD0DFB407AAA3233CCC4E6E0ABFE7CB5A656493ADB5D4924C84A1A9817B120220208008AE2DFFCA28592D47853F415D0A5A13AC87EF4CD50D97B4C7ADCEE03130

I could easily find the first “30” and the r and s values would work [Try here]:

3044022067BCD0DFB407AAA3233CCC4E6E0ABFE7CB5A656493ADB5D4924C84A1A9817B120220208008AE2DFFCA28592D47853F415D0A5A13AC87EF4CD50D97B4C7ADCEE03130

But, what was the “01265FAE04” part? After a bit of testing, I found it, and where the private key ID is the part after “01”: “265FAE04”. As an integer, “265FAE04” is 643804676. And so I found it:

Signature generator
Text: hello
Type: ECDSA_P256
Sig (Base64): ASZfrgQwRAIgZ7zQ37QHqqMjPMxObgq/58taZWSTrbXUkkyEoamBexICICCACK4t/8ooWS1HhT9BXQpaE6yH70zVDZe0x63O4DEw
Sig (Hex): 01 265FAE04 3044022067BCD0DFB407AAA3233CCC4E6E0ABFE7CB5A656493ADB5D4924C84A1A9817B120220208008AE2DFFCA28592D47853F415D0A5A13AC87EF4CD50D97B4C7ADCEE03130
Valid Signature
Printing out key:
{
"primaryKeyId": 643804676,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey",
"keyMaterialType": "ASYMMETRIC_PRIVATE",
"value": "EkwSBggDEAIYAhogSxH0Ta+brkGS9KTFyqM1i+nn05ukrs4IJZk3OcSNGAsiIAZ+ijm1cI/55L/Ldx0p8+Vo92y5XjMtPqLobyR96tlwGiBtCNp1QkmBTqqW1uiopnQUP2h+SqoEaD31SFBc2YNpFQ=="
},
"outputPrefixType": "TINK",
"keyId": 643804676,
"status": "ENABLED"
}]
}

Thus Google Tink was adding the private key ID to the start of the DER-encoded format, with a fairly non-standard identifier (“01”). And so I modified the Java code to give this [here]:

Signature generator
Text: hello
Type: ECDSA_P256
Sig (Base64): AXiFu/wwRQIgL6AykSAiPhvb72gs6XNXmr+eab8B/tDM2tGmuodc6WYCIQCf1GCvjgKT/sD5idmfC3kdaUMDcBLRJjUI6Ug/0VTQeg==
Sig (Hex): 017885BBFC304502202FA0329120223E1BDBEF682CE973579ABF9E69BF01FED0CCDAD1A6BA875CE9660221009FD460AF8E0293FEC0F989D99F0B791D6943037012D1263508E9483FD154D07A
ID (Hex): 7885BBFC
DER: 304502202FA0329120223E1BDBEF682CE973579ABF9E69BF01FED0CCDAD1A6BA875CE9660221009FD460AF8E0293FEC0F989D99F0B791D6943037012D1263508E9483FD154D07A
Valid Signature
Printing out key:
{
"primaryKeyId": 2022030332,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPrivateKey",
"keyMaterialType": "ASYMMETRIC_PRIVATE",
"value": "Ek4SBggDEAIYAhohAPbBKDrcrjm4QNi67tQjPmkuFNCJ15r4/7XZEYHRehmbIiEA+h1iwjG6UjW/y6oSzmY6TmRU6wF6/XWl7WcYpAqIraoaIQCl609MbUcOxTIGmK5ByBoE6C0ze4d9zrPSiZ/ADqK/Jg=="
},
"outputPrefixType": "TINK",
"keyId": 2022030332,
"status": "ENABLED"
}]
}
Printing out public key:
{
"primaryKeyId": 2022030332,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.EcdsaPublicKey",
"keyMaterialType": "ASYMMETRIC_PUBLIC",
"value": "EgYIAxACGAIaIQD2wSg63K45uEDYuu7UIz5pLhTQidea+P+12RGB0XoZmyIhAPodYsIxulI1v8uqEs5mOk5kVOsBev11pe1nGKQKiK2q"
},
"outputPrefixType": "TINK",
"keyId": 2022030332,
"status": "ENABLED"
}]
}

And I changed my DER reader to support the private key identity:

if (der.startswith("01")):
id = der[2:10]
print ("ID: ",id, int(id,16))
der=der[10:]

And which now gives the following for a Google Tink signature:

ID:  265FAE04 643804676
DER: 3044022067BCD0DFB407AAA3233CCC4E6E0ABFE7CB5A656493ADB5D4924C84A1A9817B120220208008AE2DFFCA28592D47853F415D0A5A13AC87EF4CD50D97B4C7ADCEE03130
[U] SEQUENCE (30)
[U] INTEGER (02): 46921832246522379805089242483517494185254635629329806132340795856015096642322
[U] INTEGER (02): 14700227488801930926224579527281498980414356020925332991028518552475415884080
-----BEGIN PUBLIC KEY-----
MEQCIGe80N+0B6qjIzzMTm4Kv+fLWmVkk6211JJMhKGpgXsSAiAggAiuLf/KKFktR4U/QV0KWhOsh+9M1Q2XtMetzuAxMA==
-----END PUBLIC KEY-----

If you are interested, here are a few videos on ECDSA: