What changed, and why it matters
This commit is a clean-up rewrite of how internal numeric values are converted into 32-byte output inside the secp256k1 cryptography library. It replaces many byte-by-byte shift-and-mask operations with a smaller number of whole-word writes using existing helper functions. The commit message explicitly states the output is unchanged, and the diff shows a direct mechanical refactoring with no change to inputs, preconditions, or callers.
No security action needed. Treat as a normal code-quality / maintainability change. Standard review and regression testing are sufficient.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors secp256k1_fe_impl_get_b32() in both the 10x26 and 5x52 field implementations. The old code extracted each output byte individually through nested shifts and masks; the new code assembles 32-bit or 64-bit words from the limbs and writes them via secp256k1_write_be32 / secp256k1_write_be64. The function contract (input must be normalized, output is 32 bytes big-endian) is preserved, and no other code paths are modified. There is no evidence of a security bug, bounds issue, or behavior change.
Changed components
src/field_10x26_impl.hsrc/field_5x52_impl.hInspect captured patch +12 / −64
diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h
index aa45434..abd17aa 100644
--- a/src/field_10x26_impl.h
+++ b/src/field_10x26_impl.h
@@ -303,38 +303,14 @@ static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
- r[0] = (a->n[9] >> 14) & 0xff;
- r[1] = (a->n[9] >> 6) & 0xff;
- r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3);
- r[3] = (a->n[8] >> 16) & 0xff;
- r[4] = (a->n[8] >> 8) & 0xff;
- r[5] = a->n[8] & 0xff;
- r[6] = (a->n[7] >> 18) & 0xff;
- r[7] = (a->n[7] >> 10) & 0xff;
- r[8] = (a->n[7] >> 2) & 0xff;
- r[9] = ((a->n[7] & 0x3) << 6) | ((a->n[6] >> 20) & 0x3f);
- r[10] = (a->n[6] >> 12) & 0xff;
- r[11] = (a->n[6] >> 4) & 0xff;
- r[12] = ((a->n[6] & 0xf) << 4) | ((a->n[5] >> 22) & 0xf);
- r[13] = (a->n[5] >> 14) & 0xff;
- r[14] = (a->n[5] >> 6) & 0xff;
- r[15] = ((a->n[5] & 0x3f) << 2) | ((a->n[4] >> 24) & 0x3);
- r[16] = (a->n[4] >> 16) & 0xff;
- r[17] = (a->n[4] >> 8) & 0xff;
- r[18] = a->n[4] & 0xff;
- r[19] = (a->n[3] >> 18) & 0xff;
- r[20] = (a->n[3] >> 10) & 0xff;
- r[21] = (a->n[3] >> 2) & 0xff;
- r[22] = ((a->n[3] & 0x3) << 6) | ((a->n[2] >> 20) & 0x3f);
- r[23] = (a->n[2] >> 12) & 0xff;
- r[24] = (a->n[2] >> 4) & 0xff;
- r[25] = ((a->n[2] & 0xf) << 4) | ((a->n[1] >> 22) & 0xf);
- r[26] = (a->n[1] >> 14) & 0xff;
- r[27] = (a->n[1] >> 6) & 0xff;
- r[28] = ((a->n[1] & 0x3f) << 2) | ((a->n[0] >> 24) & 0x3);
- r[29] = (a->n[0] >> 16) & 0xff;
- r[30] = (a->n[0] >> 8) & 0xff;
- r[31] = a->n[0] & 0xff;
+ secp256k1_write_be32(&r[0], (a->n[9] << 10) | (a->n[8] >> 16));
+ secp256k1_write_be32(&r[4], (a->n[8] << 16) | (a->n[7] >> 10));
+ secp256k1_write_be32(&r[8], (a->n[7] << 22) | (a->n[6] >> 4));
+ secp256k1_write_be32(&r[12], (a->n[6] << 28) | (a->n[5] << 2) | (a->n[4] >> 24));
+ secp256k1_write_be32(&r[16], (a->n[4] << 8) | (a->n[3] >> 18));
+ secp256k1_write_be32(&r[20], (a->n[3] << 14) | (a->n[2] >> 12));
+ secp256k1_write_be32(&r[24], (a->n[2] << 20) | (a->n[1] >> 6));
+ secp256k1_write_be32(&r[28], (a->n[1] << 26) | a->n[0]);
}
SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h
index 0e0e2d6..6a2987e 100644
--- a/src/field_5x52_impl.h
+++ b/src/field_5x52_impl.h
@@ -269,38 +269,10 @@ static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
- r[0] = (a->n[4] >> 40) & 0xFF;
- r[1] = (a->n[4] >> 32) & 0xFF;
- r[2] = (a->n[4] >> 24) & 0xFF;
- r[3] = (a->n[4] >> 16) & 0xFF;
- r[4] = (a->n[4] >> 8) & 0xFF;
- r[5] = a->n[4] & 0xFF;
- r[6] = (a->n[3] >> 44) & 0xFF;
- r[7] = (a->n[3] >> 36) & 0xFF;
- r[8] = (a->n[3] >> 28) & 0xFF;
- r[9] = (a->n[3] >> 20) & 0xFF;
- r[10] = (a->n[3] >> 12) & 0xFF;
- r[11] = (a->n[3] >> 4) & 0xFF;
- r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4);
- r[13] = (a->n[2] >> 40) & 0xFF;
- r[14] = (a->n[2] >> 32) & 0xFF;
- r[15] = (a->n[2] >> 24) & 0xFF;
- r[16] = (a->n[2] >> 16) & 0xFF;
- r[17] = (a->n[2] >> 8) & 0xFF;
- r[18] = a->n[2] & 0xFF;
- r[19] = (a->n[1] >> 44) & 0xFF;
- r[20] = (a->n[1] >> 36) & 0xFF;
- r[21] = (a->n[1] >> 28) & 0xFF;
- r[22] = (a->n[1] >> 20) & 0xFF;
- r[23] = (a->n[1] >> 12) & 0xFF;
- r[24] = (a->n[1] >> 4) & 0xFF;
- r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4);
- r[26] = (a->n[0] >> 40) & 0xFF;
- r[27] = (a->n[0] >> 32) & 0xFF;
- r[28] = (a->n[0] >> 24) & 0xFF;
- r[29] = (a->n[0] >> 16) & 0xFF;
- r[30] = (a->n[0] >> 8) & 0xFF;
- r[31] = a->n[0] & 0xFF;
+ secp256k1_write_be64(&r[0], (a->n[4] << 16) | (a->n[3] >> 36));
+ secp256k1_write_be64(&r[8], (a->n[3] << 28) | (a->n[2] >> 24));
+ secp256k1_write_be64(&r[16], (a->n[2] << 40) | (a->n[1] >> 12));
+ secp256k1_write_be64(&r[24], (a->n[1] << 52) | a->n[0]);
}
SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.